Remix+CloudflareでWebサイトを作る 26(display: noneとアクセシビリティ、deferとSuspence、h1タグを複数使うのは良いのか)
display: none
はアクセシビリティを悪くする
【2024-05-29】 背景
Lighthouseでスコアを色々みるようになってからWebアクセシビリティにも少しだけ気を使えるようになってきた今日このごろ。
ファイルアップロードのためにinputをtype="file"
にしてdisplay: none
にするようなコンポーネントを作成中こんな記事をみかけた。
アクセシビリティ
つまりこういうこと。
- Webサイトはいろいろな媒体・いろいろなユーザーが見るので、アクセシビリティを向上することでイケてるサイトにしよう
- アクセシビリティツリーというツリー構造のデータを生成している
- これはDOM、CSSOM(CSSから生成されるツリー構造のデータ)を元に生成される
- つまり、CSSによってはアクセシビリティ情報に影響が出てしまう
display: none
の問題点
今回の場合 display: none
を使う
→スクリーンリーダーにも要素が認識されなくなる
→アクセシビリティツリーの要素に影響が...!
MDNにも書いてある。
visibility: hidden
はダメなの?
似たような非表示系にこれがあるが違いは何か。
要素のボックスは不可視になります (描画されません) が、レイアウトには通常通り影響します。子孫要素は visibility が visible に設定されていれば可視になります。(タブ順で操作された時などに) 要素はフォーカスを受け取ることができません。
dispaly: none
はほんとうに丸ごと削除するが、visibility: none
は高さや幅を維持したまま消してくれる。
で、こちらも使用するとアクセシビリティツリーからは削除される。
【CSS】display:noneとvisibility:hiddenの違いと非表示にする際の注意点 | オジマネ から。
わかりやすい。
まとめ
ありがたや。
じゃ、どうすんのよ
hiddenを使ってもアクセシビリティに影響する。
使ってくださいと言わんばかりにこの属性があるならなんか、こう...よしなにやっといてもらえないかね?
<input type="file" accept="image/png, image/jpeg" hidden />
opacityを0にすれば?
0にしたら見えなくなるだけでアクセシビリティに影響はないんだよな。
ただ見えなくても該当箇所をクリックしたらファイル選択のモーダルが開いてしまう。
しかし、これは pointer-events: none
にすれば回避できるのでは...?
ということで書いてみよう
こんな記事を見たのでlabel
ではなくbutton
を使って書いてみる。
function FileUpload() {
const fileInput = useRef<HTMLInputElement | null>(null);
const handleClick = () => {
if (!fileInput || !fileInput.current) {
return;
}
fileInput.current.click();
};
const [src, setSrc] = useState<string>("");
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (!event || !event.target || !event.target.files) {
return;
}
const file = event.target.files[0];
setSrc(URL.createObjectURL(file));
};
return (
<div>
<button type="button" onClick={handleClick}>
{src ? (
<img
src={src}
alt="uploaded-thumbnail"
className="h-60 w-96 border object-contain rounded-xl"
/>
) : (
<div className="h-60 w-96 border object-contain rounded-xl flex items-center justify-center text-sm text-muted-foreground">
クリックして画像を選択
</div>
)}
</button>
<input
id="article-thumbnail"
ref={fileInput}
type="file"
accept="image/png, image/jpeg"
// className="opacity-0 pointer-events-none"
// 下のコメントで教えてもらったが、Tailwindにはsr-onlyというものがあるのでそれを使えば良さそう
className="sr-only" // こっちでOK
onChange={handleChange}
/>
</div>
);
}
簡易なものが作れた。
このborderで囲っている箇所の右側に見えないinput
があるんだけどpointer-event-none
のおかげでクリックしてもファイル選択モーダルが開かない。
また opacity: 0
の場合display: none
visibility: hidden
と違って、キーボードのタブフォーカスも可能になる!
ん〜これはこれで良さそうだけど、ベストプラクティスを知りたい。
明日調べる。
追記:下のコメントで書いていただいてある通りTailwindを使っているのであれば sr-only
というものが使えるとのこと👏🏻
アクセシビリティって大変じゃね?
え〜〜、こういうの細かくやってかないとスコア上がらないの?
大変そうすぎない?
そして自分はHTMLやCSSについてまだまだ何も知らないんだなぁと。。
わかります。気を使ってるときは tailwindcss だと sr-only 使いますかねえ。
お〜〜便利なものが提供されてますね!
ありがとうございます🙇🏻♂️
こっち使ってみます。
json
じゃなくてdefer
もいるよ
【2020-05-31】最近ZennのRemixのタグをちょくちょく見るんだけど以下の記事を見つけた。
loader
で重い処理をするときに、json
ではなくdefer
で返すという方法があるのか。
defer
を使うBefore/Afterの速度計測したいな。
誰でも叩けるめっちゃ重い処理するエンドポイントとか探せばありそうだけど。
この例では<Suspense>
で囲む必要がなくなったという書き方をしているけど、defer
側と同じようにfallbackの処理書きたければいるのでは...?
まだ全然理解してないけど公式もそんな感じの書き方。
無駄にスケルトンとか実装してみようかな。
ちゃんと理解したい記事
use
フックを解説してくれてるすごいボリュームの記事、理解が追いついていないのでちゃんとわかるようになりたい。
ChatGPTに聞いてみたけど、まだReact 19というものを知らないらしい。
その他
調べてるときに見つかったHydrogenのテンプレートも見てみようかな。
Render-as-you-fetchか〜学びが多かった。
明日続編も読んでみよう。
ここにデータフェッチのアプローチの違いが書かれてあるから後で読む。
今社内でめっちゃReactFlow使ってるんだけど自分もなんか記事書いてみようかな。
h1
タグは1ページに複数でもいいのか
【2024-06-02】疑問
Markdown形式で文章を書いたら#
をh1
に変換してたけどh1
が複数になってしまう。
h1
タグって1ページに1個じゃないとHTMLの本来の使い方(?)じゃなかったり、SEO的にダメみたいなのなかったっけか?
1 つのページに複数の <h1> 要素を使用することは HTML 標準では認められていますが(入れ子でない限り)、これはよい習慣とはみなされません。
結論
HTMLの構造的な意味でも、SEO的な意味でも、複数あってもOKっぽい。
HTMLの構造
ちゃんと区切ってたらいいっぽい。
<main>
<section>
<h1>Section 1 Title</h1>
<p>Content for section 1.</p>
</section>
<section>
<h1>Section 2 Title</h1>
<p>Content for section 2.</p>
</section>
<article>
<h1>Article Title</h1>
<p>Content for the article.</p>
</article>
</main>
SEO的
自分がSEOに詳しくない、かつソースが正しくない場合があるかもだがまとめるとこんな感じだった。
どこまでほんとなんだ。
-
h1
タグは検索順位への直接的な影響はない(全く関係ないわけでもないが)- 数年前までは検索順位として直接的な効果はあった
-
h1
タグは32文字以内、狙っているキーワードを入れるとSEO的に良い
参考
- h1タグとは?複数あっても良い?SEOとの関係や使用の注意点を解説 | Bowned
- 絶対に1つがルール?誤解されがちなh1タグの取り扱いについて | 株式会社タクミ
- 「h1タグが複数だとSEOで不利になる?」実際にABテストで検証 | Moz - SEOとインバウンドマーケティングの実践情報 | Web担当者Forum
Zennではどうなってる?
ZennはMarkdownで#
を書くと表示するときにはh1
に変換してる。
例1
記事の見出しで#
を使っているためh1
が複数回登場する。
目次は「◯」がh1
、「・」がh2
になっている。
例2
記事の見出しで##
を使っているためh1
が登場せず、h2
の見出しになっている
この場合、目次は「◯」がh2
、「・」がh3
になっている。
section
h1
を複数回使用していてもちゃんとsection
で囲んでいる。
article
ではない理由ってなんかるのかな。
次のScrapで違いを調べてみよう。