1:導入
例の「CSS完全に理解した」Tシャツ。
色々な方が話している通り、あれを意図的にやろうとすると実はなかなか難しい。
むしろ、「CSS完全に理解した」を再現するコードを書くたびに我々はCSSの完全理解に近づけるんじゃ無いだろうか?
CSS完全に理解したでCSS完全に理解すればもっとCSS完全に理解したできるんじゃ無いか
とにかく何かよくわからない追求心にとらわれた我々(約1名)は「CSS完全に理解した」を理解するために色々な方法でこれを再現することにしました。
以下に「CSS完全に理解した」するための数々の方法について書いていこうと思います。
2:前提
前提条件が限定されていないと無限の「CSS完全に理解した」状態を作り出せることになってしまうので、
今回は以下の画像のように、まず、「CSS完全に理解したわけではない」状態を再現し、ここに手を加えることで「CSS完全に理解した」状態を作り出すことにした。
この状態でのHTML、CSSは以下の通りである。
つまり、テキストが入ったP要素を、CSSで枠を指定したDIVに入れたシンプルなものである。
HTMLはいじらず、CSSだけいじることでCSS完全に理解する状態にしていく。
<divclass="box"><pclass="box__text">
CSS<br>完全に理解した
</p></div>
.box{position:relative;border:1pxsolid#000;border-radius:5px;width:140px;height:62px;}.box__text{margin:10px;}
※以下のCSSコードでは、付け足す部分のみを記述し、上に書かれた根幹の部分は省略する。
3:実践
基本:P要素の左側に単純な隙間を空けるパターン
まず単純にテキスト部分を左側に隙間を開けることを考えてみる。
これは、padding-left
やmargin-left
使えば可能だ。
.box__text{margin-left:60px;}
.box__text{padding-left:60px;}
しかし、ただ隙間を空けただけだと下の画像のように勝手に文字が途中で改行されてしまう。
また、position:absolute
とleft
を使用して右側にテキストを移動した場合も、途中で改行されてしまう。
.box__text{position:absolute;left:50px;}
これは親要素であるDIVの幅が固定であるためで、それに引っ張られて下層のPタグも幅が制限され、改行されてしまうのである。
そこで、このテキストの自動折り返しをキャンセルする方法を考えなければならない。
折り返しキャンセル方法1:white-space: nowrap;
文字通り改行を禁止するために使うCSSなので一番ふさわしいと思われる。line-height
などをいじればwhite-space: pre;
でも不可能ではないが、今回は再現性が低いので割愛する。
折り返しキャンセル方法2:ネガティブマージン
左側に隙間を空けた分だけのmargin-right
をマイナス値で指定すれば、結果全体の幅は保たれるので、自動折り返しをキャンセルすることができる。
折り返しキャンセル方法3:幅を指定する
親の幅に引っ張られているので、自身が幅を持てばそちらを優先することができ、結果折り返しが起こらなくなる。
以上、「左側に単純な隙間を空ける方法」と「折り返しをキャンセルする方法」の組み合わせでここまでで9種類の「CSS完全に理解した」ができる。
応用:折り返しをキャンセルする必要がないパターン
position:relative
を使う
.box__text{position:relative;left:50px;}
position: relative;
は元の高さや幅を保ったまま見た目を移動させるため、自動折り返しも起こらない。
position: absolute
とrightを使用する
position: absolute
の時にleftを使うと上記のように折り返しが発生するが、rightをマイナス値で指定する方法ならばそれは起こらない。ただ基準がテキストの幅(フォントの種類)に依存するため、正確な位置合わせは難しい。
.box__text{position:absolute;right:-42px;}
transform
を使う
transform
は「移動」ではなく「変形」なので、transformでの変形結果は幅や位置などに(見た目以上の)影響を与えない。このためもちろん自動折り返しも起こらない。
.box__text{transform:translateX(50px);}
ちなみに上記は下記と同義となる。
.box__text{transform:matrix(1,0,0,1,50,0);}
また、translateXやmatrix以外のtransformでも、下記のように無理やり右に50px移動させることができる。
/* Y軸回転→Z軸移動→Y軸回転 */.box__text{transform:rotateY(90deg)translateZ(50px)rotateY(-90deg);}/* Z軸回転→Y軸移動→Z軸回転 */.box__text{transform:rotateZ(90deg)translateY(-50px)rotateZ(-90deg);}
応用:flexを無理やり使う。
DIVにdisplay: flex;
を指定しP要素をフレックスアイテムにした場合も自動折り返しが働くが、この場合は上にあげた方法に加えてflex-shrink: 0;
でも折り返しをキャンセルすることができる。
.box{display:flex;}.box__text{padding-left:50px;flex-shrink:0;}
変態:常識にとらわれないパターン
ボックスを一旦消したあと書き直してCSS完全に理解する
とりあえず、枠の幅をautoに指定し、P要素の左に隙間を空けてみる。
.box{width:auto;}.box__text{margin-left:60px;}
当然P要素の指定に引っ張られて枠の長さが伸びてしまう。
そこで、伸びた枠を背景と同じ色のボックスで塗りつぶし、新しい枠を作ってしまう。
P要素が一番上に来るようにz-index
で調整する。
.box{width:auto;}.box::after{content:'';position:absolute;top:-1px;left:-1px;background-color:#fff;width:221px;height:64px;z-index:1;}.box::before{content:'';position:absolute;top:-1px;left:-1px;border:1pxsolid#000;border-radius:5px;width:140px;height:62px;z-index:2;}.box__text{position:relative;margin-left:60px;z-index:3;}
インデントを二重に指定してCSS完全に理解する
親のDIV要素にtext-indent
を指定し、P要素をインラインブロック要素にすると、親要素のtext-indentの影響をブロック全体で受けるようになるため、P要素はブロックごと右にずれることになる。しかしtext-indentはP要素の中にまで継承されるので、このままでは一行目の「CSS」がさらに右へずれてしまう。なのでP要素でtext-indent
をゼロに指定してこれを打ち消す必要がある。
.box{text-indent:50px;}.box__text{text-indent:0;display:inline-block;}
影文字で見た目を騙してCSS完全に理解する
本来の文字をcolor: transparent;
で透明にし、text-shadowを使ってぼかしの無い影文字を50px右に表示させることにより、スマートに枠からはみ出した文字を再現することができる。
.box__text{color:transparent;text-shadow:50px00#000;}
4: まとめ
以下に上記で解説した、数々の「CSS完全に理解した」解法をのせました。
See the Pen CSS完全に理解したでCSS完全理解する by ichimonzi (@ichimonzi) on CodePen.
おそらくこれ以上の変態の解法もあるものと思われますので、変態の皆さんはよろしければ教えてください。
皆さんのさらなるCSSの完全理解をお祈りしています。