HTML/CSSの落とし穴 ~知らないと15分損するTips集

それ、できないんすよ。
知っていれば一瞬だけど知らないと躓く、
そんな些細ながらも侮れない豆知識を紹介しようと思います。
input要素に:before,:afterは使えない
仕様ですので諦めましょう。
フォームボタンに:before要素を使ってアイコンをつけたい!
みたいなシチュエーションの場合はボタン部分の
<input type=”button”>ではなく
<button>にするといいでしょう。
補足
<input>や<img>要素など、一部の要素を置換要素と呼びます。
ざっくりな理解でよければ、
閉じタグのない要素≒置換要素と覚えておくと楽でしょう。
(WEB制作の偉い人からはマサカリ投げられそうですが)
実務レベルだとそのぐらいの理解度でも問題ないですたぶん。
厳密には・・・
- 埋め込みコンテンツ(iframe要素、video要素など)
- ブラウザやOSによって表示され方が変わる、
フォームに関連する要素の一部(input要素、textarea要素など) - 画像(img要素、svg要素など)
これらの置換要素には:beforeや:afterなどの擬似要素を使うことができません。
コンテンツが現在の文書のスタイルに影響されない要素です。置換要素の位置は CSS を使用して変更することができますが、置換要素自身のコンテンツは違います。
引用元:https://developer.mozilla.org/ja/docs/Web/CSS/Replaced_element
という定義だそうで。
例を挙げるとするならば・・・
画像の位置をCSSで変更することはできても、
「画像の内容そのものを編集できるわけではない」ですよね。
そのため、必ずしも閉じタグがない要素だからといって置換要素であるとは限りません。
例えばこのように<hr>要素には擬似要素を使って装飾することができます。
でも<br>はダメみたいです。(<br>も分類上は置換要素に含まれるっぽい? 憶測ですが)
フォーム関連のタグだと、
<form>・<label>・<button>あたりは擬似要素が有効なようです。
参考URL:
imgとかinputなどの置換要素にはbefore, afterは使えないよ
意外と知らない? HTML置換要素をめぐる勘違いを深堀りしてみた
Chrome以外のブラウザではbackground-imageのアニメーションが効かない
例えば、背景画像や特定要素をフェードイン・フェードアウトさせたかったとします。
transitionやanimationでアニメーションさせる対象のプロパティとして
background-imageやdisplayを指定しても効果はありません。
たとえば、下記のようにCSSを書くと失敗します。
(hover時、アニメーションせずtest2.pngに一瞬で切り替わってしまう)
.sample {
background-image: url(‘test1.png’);
transition: background-image .4s
}
.sample:hover {
background-image: url(‘test2.png’);
}
どうすればいいかというと・・・
デモをご覧になるか下記リンクを参照ください(まさかの丸投げ)。
background-imageはアニメーション出来ない(問題と解決のコード付き)
簡単に説明するとbackground-imageではダメなので、
予め<img>タグで2枚画像を表示しておいて、
opacityをアニメーションさせることで
見かけ上表示させる画像を切り替えているといった方法で解決しています。
Google Chromeだとブラウザ側で補完してくれるようなので、
上記例のようなCSSを書いても背景画像をフェードイン/アウトさせることができます。
ただし、(現時点での)W3Cの仕様的にはChrome以外のブラウザの挙動が正常だそうなので
正しい方に合わせておきましょう。
補足
観念的な話
確かにCSSアニメーションによって
要素を拡大縮小したり、回転させたり、
位置や余白の大きさを変更したり、色を変えたりすることができます。
できることは多いです。しかし、そうであるがゆえに勘違いも起きがちです。
なぜdisplayやbackground-imageにアニメーションが効かないかというと、
中間の状態が存在しないからです。
「display: noneからdisplay: blockにアニメーションで変えたい」
というと上手くいきそうな気がしがちですが、では
「display: blockからdisplay: tableにアニメーションで変化」
させようとしたら一体何が起こると思いますか? イメージできないことでしょう。
display: blockとdisplay: tableの“中間の状態”なんてありませんからね。
background-imageでも同様です。
画像Aの位置をアニメーションさせることは可能です。
でも、画像Aから画像Bへの切り替わりをアニメーションさせることはできないんです。
画像Aと画像Bは別物ですから、切り替わっていく“中間の状態”なんてないでしょう?
・・・という観点を持っていると
何がアニメーション可能なプロパティかの識別が簡単になると思います。
CSSアニメーションって慣れるまでは中々取っつきにくいところがありますよねー。
この記事が理解の助けになれば幸いです。
ものぐさ向けお役立ちリンク
上の項で講釈を垂れてましたが、実はこれを見れば一発で分かります。
Animatable CSS properties
ここに載っていないCSSプロパティはアニメーションしないので注意です。
display: inline-blockで横並べにすると半角スペースの余白ができる
今となっては旬が過ぎたテクニックですが、
遥か昔、まだ悪しきIE10以下が地上を埋め尽くしていた暗黒の時代では
要素の横並べと言えばdisplay: inline-blockを用いるのがメジャーでした。
例として下記画像をご覧ください。
隙間なく並べる想定だったにも関わらず、不自然な空白が生じています。
それでは困るのでdisplay: flexを使いましょう。
今はもうそれが許される時代です。
悪しき因習は絶たれるべきなのです。
display: flexを使わず手っ取り早く解決する方法
・・・さすがに怒られそうなので、
CSSに触らずに直す方法も紹介しておきましょう。
その方法とは・・・!
こうじゃ。
対象となる要素間の閉じタグから次の開始タグまでをコメントアウトすると解決です。
<div class=”demo02_col”>項目</div><div class=”demo02_col”>項目</div><div class=”demo02_col”>項目</div>
といったように改行せずに続けて書いても解決します。
table-cellを使ったり親要素をfont-size: 0にしたりする方法もありますが、
スマートなやり口ではないので省きます(あとliの終了タグを省略するとかね)。
もう今の時代には不必要なテクニックだと思うので、忘れましょう。
そもそもの原因
解決方法は分かりました。
そもそも何故こんなキモチワルイ空白ができてしまうのかモヤッとしますよね。
これは、インライン要素(およびインラインブロック要素)の場合、
ソース上の改行が半角スペースとして出力されてしまう仕様のためです。
厳密には半角スペースではなく、空白類文字というらしい。
参考URL:
inline要素内での改行と空白
なんでそんな仕様なのかって・・・?
さあ・・・(遠い目)。
具体的な根拠が載った情報源は見つかりませんでしたが、
どうにも英語圏だとそっちのが便利っぽいからみたいです。
そんなこと言われても日本人にはピンと来ないので例を挙げます。
<span>bed</span>
<span>room</span>
と、ソース上に書いたとします。
日本語に訳すまでもないですが「ベッド」と「部屋」という意味の単語ですね。
この改行が無視されてしまった場合、下記のような出力結果になってしまいます。
bedroom
「寝室」、と意図しない複合名詞にされてしまいます。
(実際にはbed roomと出力されるのですが)
このように一行目と二行目の相関がないつもりで書いたはずの
単語が繋がってしまうと困る場合が考えられます。
あと、ピリオドの直後にスペースなしで文字が続くのも英語圏的にはおかしいですしね。
まあそんな海の向こうの事情っぽいっすよ~。知らんけど。
おわりに
また小ネタが溜まったらまとめたいと思います。
こういう一見常識っぽいノウハウって誰も教えてくれないから意外と躓きがちですよね。
デモも用意したので説明が分かりづらかったらそちらも参考にしてください。
-
前の記事
フロントエンドエンジニア歴4年生の通信簿・前編 2018.04.10
-
次の記事
フロントエンドエンジニア歴4年生の通信簿・後編 2018.04.24