現在のCSSを整理するために本書を手に取った。11冊目。
CSSの全体整理のための本。とりあえずこの本でCSS実装系はいったん終わり。
- 作成したデモサイト
-
https://cerulean-chebakia-bdaf42.netlify.app/index.html
- モバイルフレンドリーテスト
- PageSpeed Insights
- HTML文法チェック
-
https://cerulean-chebakia-bdaf42.netlify.app/index.html
まとめ
レイアウトのバリエーション
- 両端配置
- Flexbox
justify-content: space-between
,margin-right: auto
- Grid
grid-auto-flow: column; grid-template-columns: 1fr auto
- Flexbox
- 縦横中央配置
- Grid
justify-items: center; align-content: center
- アイテムが1つだけなら
place-items: center
- アイテムが1つだけなら
- Flexbox
flex-direction: column; justify-content: center; align-items: center
- Grid
- タイル状配置
- Grid
- 列の数が固定
-
grid-template-columns: repeat(3, 1fr); gap: 32px 25px;
- アイテム配置を指定する
posts-container > :nth-child(5)
- アイテム配置を指定する
-
- 列の数が変わる
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr))
- 列の数が固定
- Flexbox
flex-wrap: wrap
,.container > * { width: 33.333% }
- gapで余白調整
gap: 32px 25px
,width: calc(33.33% - (25px * 2 / 3))
- justify-contentで余白調整
row-gap: 32px
,width: 32%
- paddingで余白調整
width: 33.33%
,padding: 0 12.5px 32px
,box-sizing: border-box
,.container { margin: 0 -12.5px -32px }
- gapで余白調整
- Grid
- 自在に配置を変更
- Grid
- テンプレート
grid-template-columns: auto auto
,grid-column: 1 / 4
- エリア
grid-template-areas: "site" ". sns"
,grid-area: site
- テンプレート
- Flexbox
position: absolute; top: 0; right: 0; height: 100%;
- Grid
- 中身に合わせたサイズで横並び配置
- Flexbox
display: flex; flex-wrap: wrap; gap: 20px;
- Grid
display: grid; grid-template-columns: repeat(auto-fit, minmax(6em, auto)); gap: 20px
- Flexbox
- カード型UI配置
- Grid
grid-template-columns: repeat(auto-fit, minmax(0, 1fr))
- Flexbox
flex-direction: column
,.container > * { flex: 1; }
- Grid
- カードの中身を上下揃えて配置
- Flexbox
flex-direction: column
,margin-top: auto
- Grid
grid-template-rows: auto 1fr auto auto
- Flexbox
- 画像とテキストを横並びに配置
- Flexbox
flex-direction: column
,.text { flex: 1 }; .img { flex: 2 };
- Grid
grid-template-columns: 1fr 2fr
- Flexbox
- 画像にテキストを重ねる
- 背景画像
.hero { height: 650px; background-image: url(img/hero.jpg); background-position: center; background-size: cover }
- Grid
grid-template-rows: 650px
,.hero > * { grid-area: 1 / 1 }
,.hero > img { width: 100%; height: 100%; object-fit: cover }
- 背景画像
- オーバーレイで表示する
position: fixed; inset: 0; z-index: 100;
- ヘッダーを上部に固定する
position: sticky; top: 0; z-index: 10;
- 記事本文の余白
margin: 1.8em 0
- Grid
display: grid; gap: 1.8em
,figure { margin: 20px 0; }
- 横幅と左右の余白
- width
width: min(92%, 1166px); margin: auto;
orwidth: 92%; max-width: 1166px; margin: auto;
- padding
max-width: 1166px; margin: auto; padding-left: 4%; padding-right: 4%;
- Grid
grid-template-columns: 1fr min(92%, 1166px) 1fr
,.grid > * { grid-column: 2; }
- width
各種設定
- 画面幅に合わせてフォントサイズを変える
font-size: clamp(48px, 5vw, 68px)
- レスポンシブイメージ
srcset/sizes
- 画像によるレイアウトシフトを防ぐ
-
<img>
のwidth/height
-
ヘッダー
両端に配置するレイアウト
- ヘッダーのようなシンプルな横並びコンテンツは
Flexbox
で両端に配置する- 3つ以上の要素の場合
- flexboxでロゴに
margin-right: auto
を指定して枠を広げる - CSS Gridでロゴに
grid-template-columns: 1fr
を割り当てる
- flexboxでロゴに
- 3つ以上の要素の場合
Flexboxとgapでのシンプルな横並び
.footer-sns {
display: flex;
gap: 24px;
}
横幅と左右の余白を調整する方法
min
関数margin: auto
で横幅と左右の余白を指定する
/* このクラス名を使って他のパーツでも同じ余白を指定する */
.w-container {
width: min(92%, 1166px);
margin: auto;
}
- Gridで余白を調整すると
/* 2列目の横幅を指定して調整する */
.grid {
display: grid;
grid-template-columns: 1fr min(92%, 1166px) 1fr;
}
.grid > * {
grid-column: 2;
}
/* 左右の列で調整する */
.grid {
display: grid;
grid-template-columns:
minmax(4%, 1fr)
minmax(auto, 1166px)
minmax(4%, 1fr);
}
.grid > * {
grid-column: 2
}
imgの下に余計な余白が入るのを防ぐ(imgのスタイルをリセットする)
- imgタグは標準ではインラインブロックボックスになっているため
img {
display: block;
/* オリジナルサイズ以上に拡大されるのを防ぎながら、親要素の横幅に合わせる */
max-width: 100%;
/* 横幅に対してオリジナルの縦横比を維持した高さにする */
height: auto;
}
ヘッダーを画面上部に固定するレイアウト
position: sticky
でヘッダーを固定する
.header {
position: sticky;
top: 0;
z-index: 10;
}
ヒーロー
縦横中央に配置するレイアウト
- FlexboxとCSS Gridどちらでも対応できる
- 今後複雑なデザインになっても対応しやすいのはCSS Grid
画面幅に合わせてfont-sizeを48pxから68pxに変化させる
.hero h1 {
font-size: clamp(48px, 5vw, 68px); /* 画面幅960pxで48px、1360pxで68px */
min-height: 0vw; /* Safariで機能させるため */
}
シンプルなボタンのサンプル
a {
color: inherit;
text-decoration: none;
}
a:hover {
filter: brightness(90%) contrast(120%);
}
a.btn {
display: block;
width: 260px;
padding: 10px;
box-sizing: border-box;
border-radius: 4px;
background-color: #e8b368;
color: #fff;
font-size: 18px;
text-align: center;
text-shadow: 0 0 6px #00000052;
}
縦横中央に配置するレイアウト
CSS Gridで設定する
.hero-container {
display: grid;
justify-items: center;
align-content: center;
height: 100%;
}
/* 縦横中央に配置するアイテムが1つだけの場合 */
.hero-container {
display: grid;
place-items: center; /* justify-items, align-itemsの値をまとめて指定する */
height: 100%;
}
Flexboxで設定する
.hero-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
}
画像にテキストを重ねるレイアウト
背景画像で表示する
.hero {
height: 650px;
background-image: url(img/hero.jpg);
background-position: center;
background-size: cover;
}
<img>
で表示する
.hero {
display: grid;
grid-template-rows: 650px;
}
.hero > * {
/* 「grid-row1; grid-column: 1;」をまとめて指定する */
grid-area: 1 / 1;
}
.hero > img {
width: 100%;
height: 100%;
object-fit: cover;
}
画像とテキスト
横並びにするレイアウト
- 配置を逆転させるときはFlexboxの方がわかりやすくなる
Flexboxのrow-reverseを使用する
/* 連続して並べた場合に上要素のpaddingで間隔を調整する */
.imgtext + .imgtext {
padding-top: 0;
}
.imgtext-container {
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.imgtext-container {
flex-direction: row;
align-items: center;
gap: clamp(45px, 6vw, 80px); /* 余白を可変にする */
}
/* imagetext-containerに、reverseが指定されたときだけ配置を逆にする */
.imgtext-container.reverse {
flex-direction: row-reverse;
}
.imgtext-container > .text {
flex: 1;
min-width: 17em; /* テキスト折り返しで崩れるので最小幅を指定する */
}
.imgtext-container > .img {
flex: 2;
}
}
CSS Gridを使用する
.imgtext-container {
display: grid;
gap: clamp(45px, 6vw, 80px);
}
.imgtext-container.reverse > .text {
order: 2;
}
.imgtext-container.reverse > .img {
order: 1;
}
@media (min-width: 768px) {
.imgtext-container {
grid-template-columns: 1fr 2fr;
align-items: center;
}
.imgtext-container.reverse {
grid-template-columns: 2fr 1fr;
}
}
可変サイズフォントの下線の余白をemで指定して対応する
.heading-decoration {
font-size: clamp(30px, 3vw, 40px);
min-height: 0vw; /* Safari用 */
}
.heading-decoration::after {
display: block;
content: "";
width: 160px;
height: 9px;
border-top: solid 1px #b72661;
margin-top: 0.6em;
}
見出しフォントをパーツ外側に配置する
.heading {
position: absolute;
/* パーツの上の余白から外側に出すサイズ(0.6em)をマイナス指定する */
top: calc((var(--v-space) + 0.6em) * -1);
}
Chrome, Safariで:hoverを反映させるため、<a>
にdisplay: blockを指定する
.post a {
display: block;
}
article画像を3:2の縦横比に揃える
.post img {
aspect-ratio: 3 / 2;
object-fit: cover;
width: 100%; /* aspect-ratioの設定を反映させるために必要 */
}
タイル状に並べるレイアウト
CSS Gridでタイル状にする
.posts-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 32px 25px;
}
@media (min-width: 768px) {
.posts-container {
grid-template-columns: repeat(3, 1fr);
}
}
特定のアイテムの配置をグリッドで指定する(5つめだけ大きく配置する)
.posts-container > :nth-child(5) {
grid-column: 1 / span 2;
grid-row: 1 / span 2;
}
.posts-container > :nth-child(5) img {
aspect-ratio: 3 / 2.5;
}
@media
を使用せず、コンテナの横幅に合わせてタイル状に並べるレイアウト
CSS Gridで並べる
- 「特定のブレークポイントで2列と3列を切り替える」ような制御は難しくなる
.posts-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 32px 25px;
}
Flexboxで並べる
.posts-container {
display: flex;
flex-wrap: wrap;
gap: 32px 25px;
}
.posts-container > * {
flex-grow: 1;
width: 200px;
}
Flexboxで設定する
- gapで調整する
- gapを入れた分だけ横幅を短くする
- justify-contentで調整する(アイテム数を5件などに変えると崩れる)
- アイテムの横幅値余白を含めて調整する
- paddingを入れて、border-boxを指定する
gapで調整する
.posts-container {
display: flex;
flex-wrap: wrap;
gap: 32px 25px;
}
.posts-container > * {
/* 横幅50%から、25pxのギャップを1つ分を2分割したサイズを引く */
width: calc(50% - (25px * 1 / 2));
}
@media (min-width: 768px) {
.posts-container > * {
width: calc(33.33% - (25px * 2 / 3));
}
}
フッター
Gridでアイコンを正方形の中に表示する
.footer-sns a {
display: grid;
place-items: center; /* 縦横中央に配置する(要素が1つだけの場合) */
width: 36px;
aspect-ratio: 1 / 1;
background-color: #cccccc;
color: #ffffff;
clip-path: circle(50%);
}
記事
本文の構成要素の感覚をブラウザ標準の設定に戻す(特定クラスの特定要素を:whereで指定する)
.entry-container :where(h1, h2, h3, h4, h5, h6, p, figure, ul) {
margin-top: revert;
margin-bottom: revert;
padding: revert;
list-style: revert;
}
記事本文のレイアウト
marginの重ね合わせと、:first-child, :last-childで指定する
.entry-container p {
margin: 1.8em 0;
}
.entry-container > :first-child {
margin-top: 0;
}
.entry-container > :last-child {
margin-bottom: 0;
}
CSS Grid/Flexboxで設定する
/* Grid */
.entry-container {
display: grid;
gap: 1.8em;
}
/* Flexbox */
.entry-container {
display: flex;
flex-direction: column;
gap: 1.8em;
}
複数の適用先をまとめて指定する
- 詳細度の違い
:is()
:where()
プラン
ボタンをwidth: autoにして左右いっぱいに広げる
.plan .btn {
width: auto;
}
カード内のCTAボタンを下に揃えて表示を統一する
Flexboxで設定する
.plan .price {
margin-top: auto; /* 余剰スペースが割り当てられる */
...
}
CSS Gridで設定する
.plan {
display: grid;
grid-template-rows: auto 1fr auto auto; /* 2列目に余剰スペースを割り当てる */
}
カード型UIのレイアウト
CSS Gridで設定する
.plans-container {
display: grid;
gap: 27px;
}
@media (min-width: 768px) {
.plans-container {
/* 並べるカードの数を固定する */
grid-template-columns: repeat(3, 1fr);
/* カードの数を変えても対応できるようにする */
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
/* 複数行でレイアウトする場合 */
grid-template-columns: repeat(2, 1fr);
}
}
Flexboxで設定する
.plans-container {
display: flex;
flex-direction: column;
gap: 27px;
}
@media (min-width: 768px){
.plans-container {
flex-direction: row;
}
.plans-container > * {
flex: 1;
/* 複数行でレイアウトする場合 */
width: calc(50% - (27px * 1 / 2));
box-sizing: border-box;
}
}
ナビゲーション
position: fixedでオーバーレイ表示する
@media (max-width: 767px) {
.nav {
position: fixed;
inset: 0; /* 上下左右から内側に0の距離に揃える */
z-index: 100;
background-color: #4e483ae6;
}
.nav ul {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
gap: 40px;
color: #ffffff;
}
}
ボタンクリックでメニューを表示する
position: fixed, inset: 0
で設定する
<button
class="navbtn"
onclick="document.querySelector('html').classList.toggle('open')"
>
<i class="fas fa-bars"></i>
<span class="sr-only">MENU</span>
</button>
@media (max-width: 767px) {
.nav {
position: fixed;
inset: 0 -100% 0 100%; /* 右画面外に配置する */
z-index: 100;
background-color: #4e483ae6;
/* top, left, width, heightで設定する場合 */
top: 0;
left: 100%;
width: 100%;
height: 100%;
z-index: 100
transition: transform 0.3s;
}
.open .nav {
transform: translate(-100%, 0); /* navの横幅分だけ左移動させる */
}
/* 不要なスクロール発生を防ぐ */
.open body {
position: fixed;
overflow: hidden;
}
.nav ul {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
gap: 40px;
color: #ffffff;
}
}