├── .editorconfig
├── .eleventy.js
├── .firebaserc
├── .github
├── ISSUE_TEMPLATE
│ └── design-docs.yaml
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── build-deploy.yml
│ ├── deploy-preview.yml
│ ├── publish-webbundle.yml
│ ├── test.yml
│ └── visual-regression-test.yml
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .lighthouserc.json
├── .node-version
├── .prettierignore
├── .prettierrc
├── .reg-suit
└── actual_images
│ └── .gitkeep
├── .renovaterc.json
├── .textlintrc
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── firebase.json
├── npm_scripts
└── scrape.js
├── package-lock.json
├── package.json
├── prh.yml
├── regconfig.json
└── src
├── 1
├── 1
│ └── 1.md
├── 2
│ └── 1.md
├── 3
│ ├── 1.md
│ ├── 2.md
│ ├── 3.md
│ ├── 4.md
│ └── 5.md
└── 4
│ ├── 1.md
│ ├── 10.md
│ ├── 13.md
│ ├── 2.md
│ ├── 3.md
│ ├── 4.md
│ ├── 7.md
│ └── 8.md
├── 2
├── 1
│ ├── 1.md
│ ├── 2.md
│ └── 4.md
├── 2
│ ├── 1.md
│ ├── 2.md
│ └── 4.md
├── 3
│ ├── 1.md
│ └── 3.md
├── 4
│ ├── 1.md
│ ├── 10.md
│ ├── 2.md
│ ├── 3.md
│ ├── 4.md
│ ├── 5.md
│ ├── 6.md
│ ├── 7.md
│ └── 8.md
└── 5
│ ├── 1.md
│ ├── 2.md
│ ├── 3.md
│ ├── 4.md
│ └── 5.md
├── 3
├── 1
│ ├── 1.md
│ ├── 3.md
│ └── 5.md
├── 2
│ ├── 1.md
│ ├── 2.md
│ ├── 3.md
│ └── 4.md
└── 3
│ ├── 1.md
│ ├── 2.md
│ ├── 3.md
│ ├── 4.md
│ └── 5.md
├── 4
└── 1
│ ├── 1.md
│ ├── 2.md
│ └── 3.md
├── .nojekyll
├── 404.md
├── _data
└── site.js
├── _filters
├── filterByGuidelineNumber.js
└── scNumberToPath.js
├── _includes
├── 404.njk
├── index.njk
├── macros
│ └── successCriteriaList.njk
├── partials
│ ├── footer.njk
│ ├── header.njk
│ ├── level.njk
│ ├── meta.html
│ ├── meta.njk
│ └── script.njk
└── single.njk
├── _shortcodes
└── label.js
├── _utils
└── scToNumberForCompare.js
├── favicon.ico
├── img
├── 1
│ ├── 2
│ │ └── 1
│ │ │ └── movie.png
│ ├── 3
│ │ ├── 3
│ │ │ ├── 1.3.3_ng.png
│ │ │ └── 1.3.3_ok.png
│ │ └── 5
│ │ │ └── autocomplete.png
│ └── 4
│ │ ├── 1
│ │ ├── 1.png
│ │ ├── 2.png
│ │ └── 3.png
│ │ ├── 8
│ │ └── 1.4.8.svg
│ │ └── 13
│ │ ├── 1.4.13_NG.mp4
│ │ └── 1.4.13_OK.mp4
├── 2
│ ├── 2
│ │ ├── 2
│ │ │ ├── 2.2.2_1_NG.svg
│ │ │ ├── 2.2.2_1_OK.svg
│ │ │ ├── 2.2.2_2_NG.mp4
│ │ │ └── 2.2.2_2_OK.mp4
│ │ └── 4
│ │ │ ├── 2.2.4_ng.png
│ │ │ └── 2.2.4_ok.png
│ ├── 4
│ │ ├── 2
│ │ │ ├── 2.4.2_1.svg
│ │ │ └── 2.4.2_2.svg
│ │ ├── 4
│ │ │ ├── 2.4.4_1.svg
│ │ │ ├── 2.4.4_2.svg
│ │ │ ├── 2.4.4_3.svg
│ │ │ ├── 2.4.4_4.svg
│ │ │ ├── 2.4.4_ng.svg
│ │ │ └── 2.4.4_ok.svg
│ │ ├── 7
│ │ │ ├── 1.png
│ │ │ └── 2.png
│ │ └── 8
│ │ │ ├── 2.4.8_ng.svg
│ │ │ └── 2.4.8_ok.svg
│ └── 5
│ │ └── 5
│ │ ├── 2.5.5_1_ng.jpg
│ │ ├── 2.5.5_1_ok.jpg
│ │ ├── 2.5.5_2_ng.jpg
│ │ └── 2.5.5_2_ok.jpg
├── 3
│ ├── 1
│ │ └── 5
│ │ │ └── 1.png
│ ├── 2
│ │ ├── 2
│ │ │ ├── 3.2.2_B_NG.mp4
│ │ │ ├── 3.2.2_B_OK.mp4
│ │ │ ├── 3.2.2_C_NG.mp4
│ │ │ ├── 3.2.2_C_OK.mp4
│ │ │ └── 3.3.2_A_OK.svg
│ │ └── 4
│ │ │ └── 3.2.4.png
│ └── 3
│ │ ├── 1
│ │ ├── 3.3.1_ng.png
│ │ └── 3.3.1_ok.png
│ │ ├── 2
│ │ ├── 3.3.2_ng.png
│ │ └── 3.3.2_ok.png
│ │ ├── 3
│ │ ├── 3.3.3_1.png
│ │ └── 3.3.3_2.png
│ │ └── 5
│ │ ├── 3.3.5_ng.svg
│ │ └── 3.3.5_ok.svg
├── 4
│ └── 1
│ │ └── 2
│ │ ├── .DS_Store
│ │ ├── underline_tab.png
│ │ ├── underline_tab_focused.png
│ │ ├── web_test1.png
│ │ └── web_test2.png
├── apple-touch-icon.png
├── icon
│ ├── circle_bold.svg
│ ├── cross_bold.svg
│ ├── minus_bold.svg
│ └── plus_bold.svg
├── logo-ameba-inverse.svg
├── logo-ameba.svg
├── logo-cyberagent-inverse.svg
├── logo-cyberagent.svg
└── ogp
│ ├── default.png
│ ├── ogp_1.1.1.png
│ ├── ogp_1.2.1.png
│ ├── ogp_1.3.1.png
│ ├── ogp_1.3.2.png
│ ├── ogp_1.3.3.png
│ ├── ogp_1.3.4.png
│ ├── ogp_1.3.5.png
│ ├── ogp_1.4.1.png
│ ├── ogp_1.4.10.png
│ ├── ogp_1.4.13.png
│ ├── ogp_1.4.2.png
│ ├── ogp_1.4.3.png
│ ├── ogp_1.4.4.png
│ ├── ogp_1.4.7.png
│ ├── ogp_1.4.8.png
│ ├── ogp_2.1.1.png
│ ├── ogp_2.1.2.png
│ ├── ogp_2.1.4.png
│ ├── ogp_2.2.1.png
│ ├── ogp_2.2.2.png
│ ├── ogp_2.2.4.png
│ ├── ogp_2.3.1.png
│ ├── ogp_2.3.3.png
│ ├── ogp_2.4.1.png
│ ├── ogp_2.4.10.png
│ ├── ogp_2.4.2.png
│ ├── ogp_2.4.3.png
│ ├── ogp_2.4.4.png
│ ├── ogp_2.4.5.png
│ ├── ogp_2.4.6.png
│ ├── ogp_2.4.7.png
│ ├── ogp_2.4.8.png
│ ├── ogp_2.5.1.png
│ ├── ogp_2.5.2.png
│ ├── ogp_2.5.3.png
│ ├── ogp_2.5.4.png
│ ├── ogp_2.5.5.png
│ ├── ogp_3.1.1.png
│ ├── ogp_3.1.3.png
│ ├── ogp_3.1.5.png
│ ├── ogp_3.2.1.png
│ ├── ogp_3.2.2.png
│ ├── ogp_3.2.3.png
│ ├── ogp_3.2.4.png
│ ├── ogp_3.3.1.png
│ ├── ogp_3.3.2.png
│ ├── ogp_3.3.3.png
│ ├── ogp_3.3.4.png
│ ├── ogp_3.3.5.png
│ ├── ogp_4.1.1.png
│ ├── ogp_4.1.2.png
│ └── ogp_4.1.3.png
├── index.md
├── robots.txt.njk
├── services
└── index.md
├── sitemap.xml.njk
├── src
└── index.md
└── styles
├── common
├── base.css
├── color.css
├── container.css
├── figure.css
├── footer.css
├── header.css
├── heading.css
├── image.css
├── index.css
├── label.css
├── license.css
├── overrides.css
├── rule_label.css
└── theme.css
├── default.css
├── default
├── heading.css
└── index.css
├── detail.css
├── detail
├── code.css
├── details.css
├── heading.css
└── index.css
├── highlight.js-dark.css
└── highlight.js-light.css
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | indent_style = space
3 | end_of_line = lf
4 | indent_size = 2
5 | charset = utf-8
6 | trim_trailing_whitespace = true
7 | insert_final_newline = true
8 |
9 | [*.md]
10 | trim_trailing_whitespace = false
11 |
--------------------------------------------------------------------------------
/.eleventy.js:
--------------------------------------------------------------------------------
1 | module.exports = (eleventyConfig) => {
2 | // Build setting
3 | eleventyConfig.addPassthroughCopy('src/img');
4 | eleventyConfig.addPassthroughCopy('src/favicon.ico');
5 | eleventyConfig.addPassthroughCopy('src/.nojekyll');
6 |
7 | // Render markdown settings
8 | const markdownIt = require('markdown-it');
9 | const markdownItAnchor = require('markdown-it-anchor');
10 | const markdownLib = markdownIt({
11 | html: true,
12 | linkify: false,
13 | }).use(markdownItAnchor, {
14 | level: [1, 2, 3],
15 | tabIndex: false,
16 | permalink: markdownItAnchor.permalink.headerLink({
17 | safariReaderFix: true,
18 | }),
19 | });
20 |
21 | eleventyConfig.setLibrary('md', markdownLib);
22 |
23 | // Serve setting
24 | eleventyConfig.addWatchTarget('./src/styles');
25 |
26 | eleventyConfig.setServerOptions({
27 | port: '3000',
28 | });
29 |
30 | // Filters
31 | const filterByGuidelineNumber = require('./src/_filters/filterByGuidelineNumber');
32 | eleventyConfig.addFilter('filterByGuidelineNumber', filterByGuidelineNumber);
33 |
34 | const scNumberToPath = require('./src/_filters/scNumberToPath');
35 | eleventyConfig.addFilter('scNumberToPath', scNumberToPath);
36 |
37 | // ShortCodes
38 | const labelShortCode = require('./src/_shortcodes/label');
39 | eleventyConfig.addPairedShortcode('label', labelShortCode);
40 |
41 | const scToNumberForCompare = require('./src/_utils/scToNumberForCompare');
42 |
43 | // Collections
44 | eleventyConfig.addCollection('SC', (collectionApi) => {
45 | const SC = collectionApi.getFilteredByTag('sc').sort((a, b) => {
46 | return (
47 | scToNumberForCompare(a.data.number) -
48 | scToNumberForCompare(b.data.number)
49 | );
50 | });
51 | return SC;
52 | });
53 |
54 | return {
55 | dir: {
56 | input: 'src',
57 | output: 'public',
58 | },
59 | templateFormats: ['md', 'njk'],
60 | markdownTemplateEngine: 'njk',
61 | };
62 | };
63 |
--------------------------------------------------------------------------------
/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "ameba-spindle"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/design-docs.yaml:
--------------------------------------------------------------------------------
1 | name: 🎨 Design docs
2 | description: 要点をまとめた設計書を書くためのテンプレートです
3 | body:
4 | - type: textarea
5 | attributes:
6 | label: 概要 / Overview
7 | description: どういった機能を実装するのか概要を書きましょう。
8 | validations:
9 | required: true
10 | - type: textarea
11 | attributes:
12 | label: 関連リンク / Related link
13 | description: 関連するissueやURLなどを書くと良いでしょう。
14 | validations:
15 | required: false
16 | - type: textarea
17 | attributes:
18 | label: その他 / Others
19 | description: その他申し送りがあれば書くと良いでしょう。
20 | validations:
21 | required: false
22 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## 概要
2 |
3 |
4 | ## 関連リンク
5 |
6 |
7 |
8 | ## 確認項目
9 | Pull Requestを出す前に確認しましょう。
10 |
11 | - [ ] コミットは適切にまとめられているか
12 | - [ ] Pull Requestの概要を適切に書いたか
13 | - [ ] レビュワーの指定をしているか
14 | - [ ] textlintを実行しエラーが出ていないか
15 | - [ ] Accessibility
16 | - [ ] altは適切に設定したか([参考(1.1.1 画像に代替テキストを提供する)](https://openameba.github.io/a11y-guidelines/1/1/1/))
17 |
18 | ## その他
19 |
20 |
--------------------------------------------------------------------------------
/.github/workflows/build-deploy.yml:
--------------------------------------------------------------------------------
1 | name: build deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
13 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
14 | with:
15 | node-version-file: 'package.json'
16 | - run: npm ci
17 | - run: npm run build
18 | - name: Create CNAME file to apply custom domain
19 | run: echo 'a11y-guidelines.ameba.design' > public/CNAME
20 | - name: Upload artifacts
21 | uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
22 | with:
23 | path: public
24 | deploy:
25 | needs:
26 | - build
27 | permissions:
28 | pages: write
29 | id-token: write
30 | environment:
31 | name: github-pages
32 | url: ${{ steps.deployment.outputs.page_url }}
33 | runs-on: ubuntu-latest
34 | steps:
35 | - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
36 | id: deployment
37 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-preview.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to Preview Channel
2 |
3 | on:
4 | pull_request:
5 | paths:
6 | - 'src/**'
7 | - '.eleventy.js'
8 | - '.firebaserc'
9 | - 'firebase.json'
10 | - 'package.json'
11 | - 'package-lock.json'
12 |
13 | jobs:
14 | build_and_preview:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
18 | - name: Build Site
19 | run: |
20 | npm ci
21 | npm run build
22 | - uses: FirebaseExtended/action-hosting-deploy@0cbcac4740c2bfb00d632f0b863b57713124eb5a # v0.9.0
23 | with:
24 | repoToken: ${{ secrets.GITHUB_TOKEN }}
25 | firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
26 | expires: 7d
27 |
--------------------------------------------------------------------------------
/.github/workflows/publish-webbundle.yml:
--------------------------------------------------------------------------------
1 | name: Publish Web Bundle
2 |
3 | on:
4 | # Our web bundle is published manually now,
5 | # but this trigger is going to be changed to an event that guideline has been updated
6 | push:
7 | branches:
8 | - publish-webbundle
9 |
10 | jobs:
11 | build-publish:
12 | runs-on: ubuntu-24.04
13 | env:
14 | TZ: Asia/Tokyo
15 | BUNDLE_NAME: ameba-accessibility-guidelines.wbn
16 | steps:
17 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
18 | with:
19 | ref: ${{ github.ref }}
20 |
21 | - name: Setup Node
22 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
23 | with:
24 | node-version-file: 'package.json'
25 |
26 | - name: Build Site
27 | run: |
28 | npm install
29 | npm run build
30 |
31 | - name: Install go/bundle CLI
32 | run: |
33 | # Go has been installed at the setup hugo step,
34 | # you can run setup-go action if you want to install specific version
35 | go install github.com/WICG/webpackage/go/bundle/cmd/gen-bundle@latest
36 | # Add path to run the package
37 | echo "$HOME/go/bin" >> $GITHUB_PATH
38 |
39 | - name: Generate Web Bundle 📦
40 | run: |
41 | # Create URL list from the files
42 | # - directory index: replacing /index.html with ''
43 | # - URL should be exactly the same with the link text in the document
44 | # - remove empty lines
45 | # - add hosting domain
46 | find public -type f | sed -e 's|/index.html||g' -e '/^$/d' -e 's|public|https://a11y-guidelines.ameba.design|g' > urls.txt
47 | # Add extra dependencies
48 | echo -e 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.min.js' >> urls.txt
49 | # Generate web bundle from URL list by following reasons:
50 | # - static directory is different from a web server implementation e.g. directory index
51 | # - to ensure HTTP response headers
52 | gen-bundle -URLList urls.txt -primaryURL https://a11y-guidelines.ameba.design -o ${{ env.BUNDLE_NAME }}
53 |
54 | - name: Generate Release ID
55 | id: generate-release-id
56 | run: |
57 | d=`date +%Y%m%d%H%M%S`
58 | echo "::set-output name=release_id::$d"
59 |
60 | - name: Create Release
61 | id: create-release
62 | uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e # v1.1.4
63 | env:
64 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65 | with:
66 | tag_name: webbundle-${{ steps.generate-release-id.outputs.release_id }}
67 | # I am waiting for https://github.com/actions/create-release/pull/19 has been merged
68 | target_commitish: ${{ github.ref }}
69 | release_name: Release Web Bundle ${{ steps.generate-release-id.outputs.release_id }}
70 | body: |
71 | 📦 New version of web bundle has been published. This means
72 |
73 | - you can read our accessibility guideline **offline**
74 | - you can send our accessibility guideline to your a11y friends
75 |
76 | Please download our web bundle named ${{ env.BUNDLE_NAME }} from the link below and check [web.dev](https://web.dev/web-bundles/#playing-around-with-web-bundles) to try out this bundle.
77 | draft: false
78 | prerelease: false
79 |
80 | - name: Upload Release Asset
81 | uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 # v1.0.2
82 | env:
83 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
84 | with:
85 | upload_url: ${{ steps.create-release.outputs.upload_url }}
86 | asset_path: ./${{ env.BUNDLE_NAME }}
87 | asset_name: ${{ env.BUNDLE_NAME }}
88 | asset_content_type: application/webbundle
89 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: test
2 |
3 | on:
4 | - push
5 | - pull_request
6 |
7 | jobs:
8 | lint:
9 | runs-on: ubuntu-latest
10 | if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
11 | env:
12 | TZ: Asia/Tokyo
13 | steps:
14 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
15 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
16 | with:
17 | node-version-file: 'package.json'
18 | - id: npm-cache-dir
19 | run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
20 | - id: npm-cache
21 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
22 | with:
23 | path: ${{ steps.npm-cache-dir.outputs.dir }}
24 | key: ${{ runner.os }}-${{ github.event_name }}-node-${{ hashFiles('**/package-lock.json') }}
25 | restore-keys: |
26 | ${{ runner.os }}-${{ github.event_name }}-node-
27 | - run: npm ci
28 | - run: npm run lint
29 | - run: npm run build
30 | - uses: treosh/lighthouse-ci-action@2f8dda6cf4de7d73b29853c3f29e73a01e297bd8 # 12.1.0
31 |
--------------------------------------------------------------------------------
/.github/workflows/visual-regression-test.yml:
--------------------------------------------------------------------------------
1 | name: visual regression test
2 |
3 | on:
4 | push:
5 | pull_request_target:
6 | types:
7 | - labeled
8 | workflow_dispatch:
9 |
10 | jobs:
11 | visual-regression-test:
12 | runs-on: ubuntu-latest
13 | # need specified label if Pull-request
14 | if: >
15 | github.event_name == 'push' ||
16 | github.event_name == 'workflow_dispatch' || (
17 | github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'allow execute workflow')
18 | )
19 | steps:
20 | - run: sudo apt-get --yes update
21 | - run: sudo apt-get --yes install fonts-noto
22 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
23 | with:
24 | fetch-depth: 0
25 | - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
26 | with:
27 | node-version: '22.x'
28 | - id: npm-cache-dir
29 | run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
30 | - id: npm-cache
31 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
32 | with:
33 | path: ${{ steps.npm-cache-dir.outputs.dir }}
34 | key: ${{ runner.os }}-${{ github.event_name }}-node-${{ hashFiles('**/package-lock.json') }}
35 | restore-keys: |
36 | ${{ runner.os }}-${{ github.event_name }}-node-
37 | - run: npm ci
38 | - run: >
39 | npm install -D
40 | puppeteer
41 | reg-keygen-git-hash-plugin
42 | reg-notify-github-plugin
43 | reg-publish-gcs-plugin
44 | - run: npm run build
45 | - run: npm start &
46 | - name: take screenshots
47 | run: >
48 | find public -type f -name '*.html' |
49 | sed -e 's/public//' |
50 | xargs node ./npm_scripts/scrape.js "${PWD}/.reg-suit/actual_images" http://localhost:3000
51 | # reg-suit needs branch name
52 | - run: git checkout ${{ github.head_ref || github.ref_name }}
53 | - run: |
54 | printf -- '%s' "$GOOGLE_APPLICATION_CREDENTIALS_JSON" | base64 --decode > "${PWD}/storage-key.json"
55 | export GOOGLE_APPLICATION_CREDENTIALS="${PWD}/storage-key.json"
56 | npx reg-suit run
57 | env:
58 | GCS_BUCKET_NAME_REG_SUIT: ${{ secrets.GCS_BUCKET_NAME_REG_SUIT }}
59 | GOOGLE_APPLICATION_CREDENTIALS_JSON: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_JSON }}
60 | REG_SUIT_NOTIFY_CLIENT_ID: ${{ secrets.REG_SUIT_NOTIFY_CLIENT_ID }}
61 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### https://raw.github.com/github/gitignore/3bb7b4b767f3f8df07e362dfa03c8bd425f16d32/Node.gitignore
2 |
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 | lerna-debug.log*
10 | .pnpm-debug.log*
11 |
12 | # Diagnostic reports (https://nodejs.org/api/report.html)
13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
14 |
15 | # Runtime data
16 | pids
17 | *.pid
18 | *.seed
19 | *.pid.lock
20 |
21 | # Directory for instrumented libs generated by jscoverage/JSCover
22 | lib-cov
23 |
24 | # Coverage directory used by tools like istanbul
25 | coverage
26 | *.lcov
27 |
28 | # nyc test coverage
29 | .nyc_output
30 |
31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
32 | .grunt
33 |
34 | # Bower dependency directory (https://bower.io/)
35 | bower_components
36 |
37 | # node-waf configuration
38 | .lock-wscript
39 |
40 | # Compiled binary addons (https://nodejs.org/api/addons.html)
41 | build/Release
42 |
43 | # Dependency directories
44 | node_modules/
45 | jspm_packages/
46 |
47 | # Snowpack dependency directory (https://snowpack.dev/)
48 | web_modules/
49 |
50 | # TypeScript cache
51 | *.tsbuildinfo
52 |
53 | # Optional npm cache directory
54 | .npm
55 |
56 | # Optional eslint cache
57 | .eslintcache
58 |
59 | # Microbundle cache
60 | .rpt2_cache/
61 | .rts2_cache_cjs/
62 | .rts2_cache_es/
63 | .rts2_cache_umd/
64 |
65 | # Optional REPL history
66 | .node_repl_history
67 |
68 | # Output of 'npm pack'
69 | *.tgz
70 |
71 | # Yarn Integrity file
72 | .yarn-integrity
73 |
74 | # dotenv environment variables file
75 | .env
76 | .env.test
77 | .env.production
78 |
79 | # parcel-bundler cache (https://parceljs.org/)
80 | .cache
81 | .parcel-cache
82 |
83 | # Next.js build output
84 | .next
85 | out
86 |
87 | # Nuxt.js build / generate output
88 | .nuxt
89 | dist
90 |
91 | # Gatsby files
92 | .cache/
93 | # Comment in the public line in if your project uses Gatsby and not Next.js
94 | # https://nextjs.org/blog/next-9-1#public-directory-support
95 | # public
96 |
97 | # vuepress build output
98 | .vuepress/dist
99 |
100 | # Serverless directories
101 | .serverless/
102 |
103 | # FuseBox cache
104 | .fusebox/
105 |
106 | # DynamoDB Local files
107 | .dynamodb/
108 |
109 | # TernJS port file
110 | .tern-port
111 |
112 | # Stores VSCode versions used for testing VSCode extensions
113 | .vscode-test
114 |
115 | # yarn v2
116 | .yarn/cache
117 | .yarn/unplugged
118 | .yarn/build-state.yml
119 | .yarn/install-state.gz
120 | .pnp.*
121 |
122 | ### a11y-guidelines
123 |
124 | /static/css/*
125 |
126 | # Lighthouse CI
127 | .lighthouseci/
128 |
129 | # reg-suit
130 | .reg-suit/actual_images/*
131 | !.reg-suit/actual_images/.gitkeep
132 |
133 | # Output
134 | /public/
135 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx lint-staged
5 |
--------------------------------------------------------------------------------
/.lighthouserc.json:
--------------------------------------------------------------------------------
1 | {
2 | "ci": {
3 | "assert": {
4 | "assertions": {
5 | "categories:accessibility": [
6 | {
7 | "error": {
8 | "minScore": 1
9 | }
10 | }
11 | ]
12 | }
13 | },
14 | "collect": {
15 | "staticDistDir": "./public",
16 | "url": [
17 | "/",
18 | "/1/1/1/",
19 | "/1/2/1/",
20 | "/1/3/1/",
21 | "/1/3/2/",
22 | "/1/3/3/",
23 | "/1/3/4/",
24 | "/1/3/5/",
25 | "/1/4/1/",
26 | "/1/4/2/",
27 | "/1/4/3/",
28 | "/1/4/4/",
29 | "/1/4/7/",
30 | "/1/4/8/",
31 | "/1/4/10/",
32 | "/1/4/13/",
33 | "/2/1/1/",
34 | "/2/1/2/",
35 | "/2/1/4/",
36 | "/2/2/1/",
37 | "/2/2/2/",
38 | "/2/2/4/",
39 | "/2/3/1/",
40 | "/2/3/3/",
41 | "/2/4/1/",
42 | "/2/4/2/",
43 | "/2/4/3/",
44 | "/2/4/4/",
45 | "/2/4/5/",
46 | "/2/4/6/",
47 | "/2/4/7/",
48 | "/2/4/8/",
49 | "/2/4/10/",
50 | "/2/5/1/",
51 | "/2/5/2/",
52 | "/2/5/3/",
53 | "/2/5/4/",
54 | "/2/5/5/",
55 | "/3/1/1/",
56 | "/3/1/3/",
57 | "/3/1/5/",
58 | "/3/2/1/",
59 | "/3/2/2/",
60 | "/3/2/3/",
61 | "/3/2/4/",
62 | "/3/3/1/",
63 | "/3/3/2/",
64 | "/3/3/3/",
65 | "/3/3/4/",
66 | "/3/3/5/",
67 | "/4/1/1/",
68 | "/4/1/2/",
69 | "/4/1/3/",
70 | "/services/"
71 | ]
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | 22.16.0
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | *.njk
2 | *.md
3 | src/img
4 | src/favcon.ico
5 | src/_includes
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/.reg-suit/actual_images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openameba/a11y-guidelines/2ca2006938740252c13ac4a5f2c8d6d419dddcbc/.reg-suit/actual_images/.gitkeep
--------------------------------------------------------------------------------
/.renovaterc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "local>openameba/renovate-config:main.json5",
5 | "local>openameba/renovate-config:npm.json5",
6 | "local>openameba/renovate-config:automerge-all.json5"
7 | ],
8 | "reviewers": [
9 | "team:spindle-working-group"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.textlintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "preset-japanese": {
4 | "no-mix-dearu-desumasu": {
5 | "preferInHeader": "である",
6 | "preferInBody": "である",
7 | "preferInList": "である",
8 | "strict": false
9 | },
10 | "sentence-length": false
11 | },
12 | "preset-jtf-style": {
13 | "3.1.1.全角文字と半角文字の間": false
14 | },
15 | "prh": {
16 | "rulePaths": [
17 | "prh.yml"
18 | ]
19 | },
20 | "@openameba/preset-ameba": true
21 | },
22 | "filters": {
23 | "comments": true,
24 | "allowlist": {
25 | "allow": [
26 | "/\\{\\{[\\s\\S]*?\\}\\}/",
27 | "/\\{%[\\s\\S]*?%\\}/",
28 | "/\\[[\\s\\S]*?\\]\\([\\s\\S]*?\\)/",
29 | "/\\u3007|\\u00D7|\\u25B3/"
30 | ]
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Ameba Accessibility Guidelines
2 |
3 | Ameba Accessibility Guidelinesは、WCAG2.1をベースに、Amebaの開発に即した事例を交えて解説するドキュメントです。
4 |
5 | Amebaのサービスはこのガイドラインに則って開発されることを推奨しています。そのため新しいガイドラインや意図の修正のPull RequestはAmeba在籍メンバーからのみとしています🙇(ごめんなさい)
6 |
7 | しかし、リンク先のミス、誤字・脱字、WCAGの誤訳・解釈の間違いなどのPull Request・issue提起は大歓迎です。
8 |
9 | もちろん、わかりづらい点や疑問に思う箇所がありましたら、お気軽にissueでお教えください!
10 |
11 | Only Ameba members can create pull requests for new guidelines or changes of intention.
12 | But, pull requests or issues to fix links, typos, missunderstanding of WCAG are welcomed! Thank you!.
13 |
14 | ## How to contribute
15 |
16 | - fork openameba/a11y-guidelines
17 | - open Pull Request from your repository
18 | - branch naming is free!
19 | - example: `fix/*`, `patch/*`, `feat/*`, etc...
20 |
21 | ## How to setup for developers
22 |
23 | お手元のマシンで確認する方法について記載しています。
24 |
25 | https://nodejs.org/en/ から node.js をダウンロードしインストールします。
26 |
27 | インストールができたら、以下のコマンドを実行します。
28 |
29 | ```console
30 | $ npm ci
31 | $ npm start
32 | ```
33 |
34 | するとHTTPサーバーが起動するので、 http://localhost:3000 にブラウザからアクセスすると確認ができます。
35 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # LICENSE
2 |
3 | ## Guidelines
4 |
5 | CC BY 4.0
6 |
7 | https://creativecommons.org/licenses/by/4.0/
8 |
9 | ## Program for build guidelines
10 |
11 | MIT
12 |
13 | Copyright 2017 CyberAgent, Inc.
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 |
21 | https://opensource.org/licenses/mit-license.php
22 |
23 | ## Ameba logos and other brand assets
24 |
25 | No License
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ameba Accessibility Guidelines
2 |
3 | [](https://github.com/openameba/a11y-guidelines/actions?query=workflow%3Atest)
4 | [](https://renovatebot.com)
5 |
6 | Work in Progress
7 |
8 | Amebaが管理する、Ameba Accessibility Guidelinesのリポジトリです。
9 | WCAG2.1をベースにしていますが、現在作成途中のガイドラインになります。
10 |
11 | ## Pull Requestなどについて
12 |
13 | [CONTRIBUTING.md](CONTRIBUTING.md) をご覧ください。
14 |
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "site": "ameba-a11y-guidelines",
4 | "public": "public",
5 | "ignore": [
6 | "firebase.json",
7 | "**/.*",
8 | "**/node_modules/**"
9 | ]
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/npm_scripts/scrape.js:
--------------------------------------------------------------------------------
1 | const { promises: fs } = require('node:fs');
2 | const path = require('node:path');
3 |
4 | const puppeteer = require('puppeteer');
5 |
6 | const dist = process.argv[2];
7 | const base = process.argv[3];
8 | const pathnames = process.argv.slice(4);
9 |
10 | async function capture(pathnames) {
11 | const browser = await puppeteer.launch({
12 | headless: true,
13 | args: ['--no-sandbox', '--disable-setuid-sandbox'],
14 | });
15 | const page = await browser.newPage();
16 |
17 | for (const pathname of pathnames) {
18 | const url = new URL(pathname, base);
19 | console.log(url.toString());
20 |
21 | const file = path.join(dist, pathname);
22 | console.log(file);
23 |
24 | const dir = path.dirname(file);
25 | console.log(dir);
26 |
27 | const output = path.join(dir, `${path.basename(file, '.html')}.png`);
28 | console.log(output);
29 |
30 | await fs.mkdir(dir, { recursive: true });
31 |
32 | let response;
33 | try {
34 | response = await page.goto(url.toString(), {
35 | waitUntil: 'load',
36 | timeout: 60000,
37 | });
38 | } catch (error) {
39 | console.error(
40 | `Error: Page ${url.toString()} loading timed out or failed: ${
41 | error.message
42 | }`
43 | );
44 | process.exitCode = 3;
45 | await page.close();
46 | break;
47 | }
48 |
49 | if (response.status() >= 400) {
50 | console.error(
51 | `Error: Page ${url.toString()} returned status code ${response.status()}`
52 | );
53 | process.exitCode = 4;
54 | await page.close();
55 | break;
56 | }
57 |
58 | const videos = await page.$$('video');
59 |
60 | if (videos.length > 0) {
61 | // hide some controls
62 | await page.addStyleTag({
63 | content: `
64 | video::-webkit-media-controls-timeline { display: none !important; }
65 | video::-webkit-media-controls-loading-indicator { display: none !important; }
66 | video::-webkit-media-controls-current-time-display { display: none !important; }
67 | video::-webkit-media-controls { visibility: hidden !important; }
68 | video::-webkit-media-controls-overlay-enclosure { display: none !important; }
69 | `,
70 | });
71 |
72 | await page.evaluate(() => {
73 | document.querySelectorAll('video').forEach((video) => {
74 | // hide controls
75 | video.controls = false;
76 | // set currentTime
77 | video.currentTime = 0;
78 | // wait for video to be ready
79 | if (video.readyState < HTMLMediaElement.HAVE_CURRENT_DATA) {
80 | video.addEventListener(
81 | 'canplaythrough',
82 | () => {
83 | video.currentTime = 0;
84 | },
85 | { once: true }
86 | );
87 | }
88 | });
89 | });
90 | }
91 |
92 | await page.screenshot({
93 | fullPage: true,
94 | path: output,
95 | });
96 | }
97 |
98 | await page.close();
99 | await browser.close();
100 | }
101 |
102 | capture(pathnames);
103 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "a11y-guidelines",
3 | "description": "Ameba Accessibility Guidelines",
4 | "version": "0.0.0",
5 | "author": "CyberAgent, Inc.",
6 | "dependencies": {
7 | "@openameba/spindle-icons": "^2.0.0",
8 | "@openameba/spindle-syntax-themes": "^2.0.0",
9 | "ameba-color-palette.css": "github:openameba/ameba-color-palette.css#feature/dark-mode",
10 | "postcss": "^8.2.6",
11 | "textlint-filter-rule-comments": "^1.2.2"
12 | },
13 | "devDependencies": {
14 | "@11ty/eleventy": "3.1.0",
15 | "@openameba/textlint-rule-preset-ameba": "0.5.1",
16 | "autoprefixer": "10.4.21",
17 | "bin-wrapper": "4.1.0",
18 | "cssnano": "7.0.7",
19 | "husky": "9.1.7",
20 | "lint-staged": "16.1.0",
21 | "markdown-it-anchor": "9.2.0",
22 | "npm-run-all2": "8.0.4",
23 | "postcss-cli": "11.0.1",
24 | "postcss-custom-properties": "14.0.5",
25 | "postcss-import": "16.1.0",
26 | "postcss-single-charset": "2.0.0",
27 | "prettier": "3.5.3",
28 | "textlint": "14.7.2",
29 | "textlint-filter-rule-allowlist": "4.0.0",
30 | "textlint-rule-preset-japanese": "10.0.4",
31 | "textlint-rule-preset-jtf-style": "3.0.2",
32 | "textlint-rule-prh": "6.1.0"
33 | },
34 | "engines": {
35 | "node": "22.15.1",
36 | "npm": "11.4.1"
37 | },
38 | "keywords": [
39 | "accessibility"
40 | ],
41 | "license": "SEE LICENSE IN LICENSE.md",
42 | "lint-staged": {
43 | "src/*.md": "textlint --dry-run",
44 | "*.+(css|js)": "prettier --check",
45 | "package.json": "npx fixpack --dryRun",
46 | "yarn.lock": "node -e 'process.exitCode = 1'"
47 | },
48 | "postcss": {
49 | "plugins": {
50 | "postcss-custom-properties": {},
51 | "postcss-import": {},
52 | "autoprefixer": {},
53 | "postcss-single-charset": {}
54 | }
55 | },
56 | "private": true,
57 | "repository": "openameba/a11y-guidelines",
58 | "scripts": {
59 | "build": "npm-run-all build:*",
60 | "build:css": "postcss src/styles/*.css --dir public/css",
61 | "build:html": "NODE_ENV=production eleventy",
62 | "build:svg": "npx cpx 'node_modules/@openameba/spindle-icons/dist/svg/+(circle_bold|minus_bold|cross_bold|plus_bold).svg' src/img/icon",
63 | "fixpack": "npx fixpack",
64 | "format": "run-p format:*",
65 | "format:prettier": "prettier --write {src,npm_scripts,.eleventy.js,package.json}",
66 | "format:text": "textlint --fix content src",
67 | "lint": "run-p lint:*",
68 | "lint:prettier": "prettier -c {src,npm_scripts,.eleventy.js,package.json}",
69 | "lint:text": "textlint content src",
70 | "prepare": "[ -n \"$CI\" ] || husky install",
71 | "serve": "DEBUG=Eleventy* eleventy --serve --watch",
72 | "start": "npm-run-all -p serve watch",
73 | "styles": "postcss src/styles/*.css --dir public/css",
74 | "watch": "npm run watch:styles",
75 | "watch:styles": "npm run styles --watch"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/prh.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | # 本ファイルは設定の仕方の見本であり、実用的な校正ルールではありません。
4 | # もし、もっと充実した別のルールを使いたい時は以下のURLを参照してください。
5 | # https://github.com/prh/rules
6 | # おすすめは media/techbooster.yml です。
7 |
8 | # 下記の説明を参考に、git submoduleとimportsを使って参照するのがよいでしょう。
9 | # リポジトリの設定 git submodule add https://github.com/prh/rules.git prh-rules
10 |
11 | # 別の設定ファイルを読み込み、mergeすることもできます。
12 | imports:
13 | # - ./prh-rules/media/techbooster.yml
14 | # - ./prh-rules/files/markdown.yml
15 | # - ./prh-rules/files/review.yml
16 |
17 | # imports にはいくつかのオプションが指定できる
18 | # - path: other-rules.yml
19 | # 連鎖的なimportを禁止する
20 | # disableImports: true
21 | # importするルールで不都合なものは殺すことができる
22 | # patternやexpectedに指定する文字列は --rules-yaml で得られるパース後の表現を使うこと
23 | # ignoreRules:
24 | # pattern: /a/ と等価
25 | # - /a/
26 | # - pattern: /a/
27 | # - expected: /b/
28 |
29 | rules:
30 |
31 | # 大文字小文字全角半角の統一
32 | - expected: Cookie
33 | # 以下と等価 正規表現には強制でgフラグが付く
34 | # - expected: Cookie
35 | # pattern: "/[CcCc][OoOo][OoOo][KkKk][IiIi][EeEe]/g"
36 | # options:
37 | # wordBoundary: false
38 | # specs: []
39 |
40 | # 変換結果についてテストも書ける
41 | - expected: jQuery
42 | specs:
43 | - from: jquery
44 | to: jQuery
45 | - from: JQUERY
46 | to: jQuery
47 |
48 | # patternは複数記述可能 patterns としてもOK
49 | - expected: ユーザー
50 | patterns:
51 | - 利用者
52 |
53 | - expected: または
54 | patterns:
55 | - 又は
56 |
57 | - expected: や
58 | patterns:
59 | - 及び
60 |
61 | - expected: ただし
62 | patterns:
63 | - 但し
64 |
65 | - expected: 代わり
66 | patterns:
67 | - かわり
68 | - がわり
69 |
70 | - expected: 文字色
71 | patterns:
72 | - テキスト色
73 |
74 | # patternには正規表現が利用可能
75 | - expected: ($1)
76 | pattern: /\(([^)]+)\)/
77 | specs:
78 | # 半角括弧を全角括弧へ
79 | - from: (そのとおり)
80 | to: (そのとおり)
81 |
82 | # 否定戻り先読みが欲しいがJSにはない… regexpMustEmptyで、特定のキャプチャグループが空であることを指定して代用とする
83 | - expected: ソフトウェア
84 | pattern: /(日経)?ソフトウエア/
85 | regexpMustEmpty: $1
86 | specs:
87 | # 普通に変換
88 | - from: 広義のソフトウエア
89 | to: 広義のソフトウェア
90 | # 日経ソフトウエア(書名)は変換しない
91 | - from: 日経ソフトウエア
92 | to: 日経ソフトウエア
93 |
94 | # 長音の統一には否定後読みを活用する そうしないと サーバー が サーバーー にされてしまったりする
95 | - expected: サーバー
96 | pattern: /サーバ(?!ー)/
97 | specs:
98 | - from: サーバ
99 | to: サーバー
100 |
101 | - expected: ユーザー
102 | pattern: /ユーザ(?!ー)/
103 | specs:
104 | - from: ユーザ
105 | to: ユーザー
106 |
--------------------------------------------------------------------------------
/regconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "core": {
3 | "actualDir": ".reg-suit/actual_images"
4 | },
5 | "plugins": {
6 | "reg-keygen-git-hash-plugin": true,
7 | "reg-notify-github-plugin": {
8 | "clientId": "$REG_SUIT_NOTIFY_CLIENT_ID"
9 | },
10 | "reg-publish-gcs-plugin": {
11 | "bucketName": "$GCS_BUCKET_NAME_REG_SUIT"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openameba/a11y-guidelines/2ca2006938740252c13ac4a5f2c8d6d419dddcbc/src/.nojekyll
--------------------------------------------------------------------------------
/src/1/1/1.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: single
3 | title: 画像に代替テキストを提供する
4 | number: 1.1.1
5 | level: A
6 | tags: sc
7 | permalink: "{{ number | scNumberToPath }}/"
8 | ---
9 |
10 | # 1.1.1 画像に代替テキストを提供する
11 |
12 | {% include "partials/level.njk" %}
13 |
14 | ## 概要
15 |
16 | 装飾ではない画像やアイコンは、代替テキストで説明する。
17 |
18 | 代替テキストとは
20 | 代替テキストとは、Webサイト内に含まれている画像や動画が何らかの原因で表示されなかったときや、スクリーンリーダーを使用するときに、画像の代わりに表示する文字・文章を指す。
21 | 広告の代替テキストについて
37 | 既存の広告システムの場合、代替テキストを設定するために必要なテキストの入力欄が設けられていないことがある。可能であれば入稿ツールなどの広告システム、またはメディア側のシステム改修が望ましい。
38 |
39 | 画像のみの広告、かつ代替テキストが画面に表示される状況(ネットワークエラー時や画像の非表示時など)では、クライアントの意図しない見た目となる。広告画像の代わりに代替テキストの「[AD] クライアント名」と表示されてしまうことが契約上問題になることがある。
40 |
41 | そういった場合、最低限操作に支障をきたさないことを目的とし、「広告であること」を伝えることが望ましい。具体的には、代替テキストに「AD」「PR」と設定するなどが考えられる。
42 | ` 要素の `alt` 属性に、画像を説明するテキストを設定する
58 |
59 | ##### 悪い実装例
60 |
61 | `
` 要素に `alt` 属性がない。
62 |
63 | ```html
64 |
65 | ```
66 |
67 | - 画像ファイル名が表示・読み上げられてしまう
68 | - 特に、リンク要素の中にこういった画像があると、ユーザーはクリックで何が起きるかが想定できない
69 | - 代替テキストが不要で装飾的な画像の場合には、空の `alt` 属性を設定する
70 |
71 | ##### 良い実装例
72 |
73 | `
` 要素の `alt` 属性に、画像を説明するテキストを設定する。
74 |
75 | ```html
76 |
77 | ```
78 |
79 | #### ラベルのないアイコンに、代替テキストを設定する
80 |
81 | ##### 悪い実装例
82 |
83 | ラベルや代替テキストがないアイコンの場合、アイコンの意味が理解できない。
84 |
85 | ```html
86 |
87 | ```
88 |
89 | ##### 良い実装例
90 |
91 | ###### 【推奨】 不可視のテキスト要素を用意し、支援技術にはアイコン自体を無視させる方法
92 |
93 |
94 | ```html
95 |
99 |
100 |
110 | ```
111 |
112 | `.visually-hidden` クラスを使用する目的としては、以下の実装を推奨とする。
113 |
114 | - 機械翻訳されやすい
115 | - 対応している支援技術が多い
116 |
117 | ###### 実装上の都合で推奨例の実装が困難な場合
118 |
119 |
親要素にラベルを設定する方法
121 |
122 | ```html
123 |
126 | ```
127 | roleをimgにした上で、ラベルを設定する方法
132 |
133 | ```html
134 |
137 | ```
138 |