うぇぶわんこ
固定ヘッダーのページ内リンクって、昔はJavaScriptで位置をずらしてたのに、今はCSSだけでできるんですかワン?
さとけん
そうなんです。CSSでできることはかなり増えました。今回は「昔はこうしていた → 今はこれだけ」で比べてみます。
Web制作を長く続けていると、「これはJavaScriptで処理するもの」「こういう場合はHTMLにクラスを追加するもの」「縦横比を維持するならpaddingを使うもの」といった、昔からのやり方が自分の中に残っていることがあります。ところが最近のCSSを改めて見ると、「え、今はこれだけでできるの?」と思うことがかなり増えました。この記事では、2026年現在、昔の実装と比べて特に便利になったと感じるCSSを10個、Before / Afterで紹介します。
この記事でわかること
Web制作を長くしているほど、最近のCSSに驚くことがある
CSSは、昔から少しずつできることを増やしてきました。FlexboxやGridが登場したときもそうでしたが、最近はさらに、JavaScriptを使っていた処理、HTML側で調整していた処理、CSSハックで対応していた処理、サイズ調整のために増やしていたメディアクエリなどを、CSS自身で解決できる場面が増えています。
もちろん、昔の方法が間違っていたわけではありません。当時はその方法が現実的だったから使っていました。大切なのは、昔のやり方を否定することではなく、「今ならもっとシンプルにできないか」と自分の中の実装方法を更新していくことだと思います。
今回は新しい順ではなく、「昔との違い」が分かりやすく、実際のWeb制作でありがたさを感じやすいものを中心に選びました。
固定ヘッダーのページ内リンク調整が楽になった scroll-padding-top
固定ヘッダーがあるサイトでページ内リンクを使うと、リンク先の見出しがヘッダーの後ろに隠れてしまうことがあります。
<a href="#service">サービスを見る</a>
<section id="service">
<h2>サービス</h2>
</section>
昔はJavaScriptで位置を計算していた
以前は移動先の位置を取得し、そこから固定ヘッダーの高さを引いてスクロールさせる方法がよく使われていました。
const headerHeight = 100;
const target = document.querySelector('#service');
const position =
target.getBoundingClientRect().top +
window.scrollY -
headerHeight;
window.scrollTo({
top: position,
behavior: 'smooth'
});
見出し側に余白を作ったり、疑似要素を使ったりする方法もありました。やりたいことは「ヘッダーの高さだけ手前で止まってほしい」だけなのに、そのための処理が増えていたわけです。
今ならCSSで書ける
html {
scroll-padding-top: 100px;
}
特定の見出しだけ調整したい場合は、対象側へscroll-margin-topを指定する方法もあります。
.heading {
scroll-margin-top: 100px;
}
これだけのために書いていたJavaScriptがなくなる。しかも「スクロールするときの余白」という目的がCSSから読み取りやすくなりました。コード量が減るだけでなく、何をしているのかが分かりやすくなったのが大きいところです。
「子要素があったら親を変える」ができる :has()
画像が入っているカードだけ、余白やレイアウトを変えたい。そんなとき、以前はHTML側に状態を表すクラスを追加することがよくありました。
昔はmodifierクラスを追加していた
<article class="card card--has-image">
<img class="card__image" src="photo.jpg" alt="">
...
</article>
場合によってはJavaScriptで子要素の有無を調べて、親へクラスを付けることもありました。CSSでは親から子を選ぶことはできても、子を条件に親を選ぶことができなかったからです。
今なら :has() で選べる
.card:has(.card__image) {
padding-top: 0;
}
これで「.card__imageを内包している.card」を条件にできます。
子要素の存在を条件に、親要素側のスタイルを切り替えられます。
.form-group:has(input:focus) {
border-color: #316fcf;
}
内部の入力欄がフォーカスされたときに、親のフォームグループを変えるような使い方もできます。
HTML側に「見た目の都合だけのクラス」を増やさなくてよいケースが出てきたのは大きな変化です。長くCSSを書いているほど、「CSSで親を条件にできるようになった」ことのありがたさを感じやすい機能だと思います。
ただし、何でも:has()で解決しようとするとセレクタが複雑になります。BEMのmodifierの方が意味的に分かりやすいなら、無理に置き換える必要はありません。また、:has()の引数は詳細度にも影響するため、複雑な条件を詰め込みすぎない方が扱いやすいです。
16:9のためのpaddingハックが不要になった aspect-ratio
YouTube動画の埋め込みや画像カードなどで、横幅に合わせて16:9の比率を維持したいケースがあります。今なら素直に書けますが、以前はpaddingの特性を利用した方法がよく使われていました。
昔は56.25%を計算していた
.video {
position: relative;
height: 0;
padding-top: 56.25%;
}
.video iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
16:9なら9 ÷ 16 × 100 = 56.25%。仕組みを知っていれば使えますが、初めてコードを見た人には「なぜ高さをpaddingで作るのか」が分かりにくい書き方でした。
今なら比率をそのまま書ける
.video {
aspect-ratio: 16 / 9;
}
.thumbnail {
aspect-ratio: 1;
}
個人的には、今回の10個の中でも昔との違いが特に分かりやすいCSSです。16:9なら「16 / 9」と、そのまま意図を書ける。コードを見た人が計算しなくても意味を理解できます。
サイズ調整だけのメディアクエリを減らせる clamp()
スマートフォンでは小さく、PCでは大きく。レスポンシブサイトでは、画面幅に合わせて文字サイズや余白を変えたいことがよくあります。
昔は段階ごとに切り替えていた
.title {
font-size: 1.5rem;
}
@media (min-width: 768px) {
.title {
font-size: 2rem;
}
}
@media (min-width: 1200px) {
.title {
font-size: 3rem;
}
}
今なら最小・可変・最大をまとめて書ける
.title {
font-size: clamp(1.5rem, 1rem + 2vw, 3rem);
}
clamp()は「最小値・推奨値・最大値」の3つを指定できます。余白にも使えます。
.section {
padding-block: clamp(3.75rem, 8vw, 7.5rem);
}
メディアクエリで段階的に切り替えるのではなく、指定した範囲で滑らかに変化させられます。文字サイズに使う場合は、remなどの相対単位を組み合わせて、ユーザー側の文字サイズ設定にも配慮したいところです。
ただし、clamp()があるからメディアクエリが不要になったわけではありません。1列から2列へ変えるようなレイアウトの切り替えにはMedia Queriesが向いています。サイズ調整だけのブレークポイントを減らしやすくなったと考えるのが実務では分かりやすいと思います。
最後の要素だけmarginを消さなくてよくなった gap
今では当たり前のように使っているgapですが、昔のmargin調整を思い出すとかなりありがたい機能です。
昔は最後だけmarginを消していた
.nav__item {
margin-right: 30px;
}
.nav__item:last-child {
margin-right: 0;
}
折り返しや上下左右の間隔まで考え始めると、さらに調整が増えます。親側にnegative marginを入れて帳尻を合わせるような実装もありました。
今なら「要素の間隔」をそのまま指定できる
.nav {
display: flex;
gap: 30px;
}
marginは「要素の外側に余白を付ける」、gapは「並んでいる要素同士の間隔を決める」と考えると意図が分かりやすくなります。今では普通すぎてありがたみを忘れていますが、最後の要素だけmarginを消していた頃を思い出すとかなり楽です。
スマホの 100vh 問題に対応しやすくなった dvh・svh・lvh
スマートフォンでheight: 100vh;と書いたのに、画面からはみ出したり、想定した高さにならなかったりすることがあります。スマートフォンのブラウザにはアドレスバーなど、表示・非表示が変化するUIがあるためです。
現在のCSSでは、従来のvhはlarge viewportを基準とするlvhと同等として扱われます。そのため、ブラウザUIが表示されている状態では「今見えている高さ」と一致しないことがあります。
昔はJavaScriptで高さを渡していた
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty(
'--vh',
`${vh}px`
);
.hero {
height: calc(var(--vh) * 100);
}
今は目的に合わせてviewport単位を選べる
.hero {
min-height: 100dvh;
}
3つのviewport高さ単位
JavaScriptで高さを測ってCSS変数へ渡す処理が不要になるケースが増えました。ただし、何にでも100dvhを使えばいいわけではありません。常に小さいviewport内へ収めたいのか、ブラウザUIの変化へ追従したいのかで使い分けます。
画面幅ではなく「そのパーツの幅」で変えられる Container Queries
Media Queriesは画面幅に応じてレイアウトを変えるときに便利です。ただ、同じカードをメインコンテンツ、サイドバー、3カラムなど複数の場所で使いたい場合、画面幅だけでは判断しにくいことがあります。
昔は置き場所やmodifierに依存していた
.card {
/* 通常 */
}
.sidebar .card {
/* サイドバー用 */
}
.card--wide {
/* 横幅が広い場合 */
}
今ならパーツ自身が置かれた幅を基準にできる
.card-wrap {
container-type: inline-size;
}
@container (min-width: 500px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
@mediaなら画面幅を見る。@containerなら、そのパーツが置かれているコンテナの幅を見る。こう考えると違いが分かりやすいです。
「サイドバーにあるからこのデザイン」ではなく、「このパーツに十分な幅があるからこのデザイン」と考えられるようになります。再利用するコンポーネントと相性の良い機能です。
カード内部の位置まで揃えやすくなった subgrid
Gridでカードを横並びにすると、カード自体の高さは揃っても、タイトルが1行・2行・3行と違うことで、本文やボタンの開始位置がずれることがあります。
昔は高さを決め打ちすることがあった
.card__title {
min-height: 3em;
}
タイトルの想定行数に合わせて高さを確保したり、各カード内部に同じGrid設定をもう一度書いたりして調整する方法です。文章量が変わると再調整が必要になることもあります。
今なら親Gridのトラックを子Gridが引き継げる
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid;
}
subgridを使うと、ネストしたGridが親Gridの行や列のトラックを引き継げます。カードごとに独立した行を作るのではなく、親側のラインを共有できるため、見出し・本文・ボタンの位置を揃えるようなレイアウトを作りやすくなります。
subgridを使うと、子Gridが親Gridの行を引き継ぎ、カードをまたいで要素の位置を揃えやすくなります。
ただし、grid-template-rows: subgrid;を単独で書けば何でも揃うわけではありません。子Gridが親Gridのトラックを実際に引き継げる構造になっている必要があります。今回の10個の中では少し理解が必要なので、図で確認すると分かりやすい機能です。
Sassを使わなくてもCSSをネストできる CSS Nesting
Sassを使っていると、セレクタをネストして書くことに慣れています。以前、このような書き方をしたければSassなどのプリプロセッサーを利用するのが一般的でした。
.card {
padding: 20px;
&:hover {
opacity: 0.8;
}
}
今はCSS自体がネストに対応している
.card {
padding: 20px;
&:hover {
opacity: 0.8;
}
& > .card__title {
font-weight: 700;
}
}
ただしSassの & とまったく同じではない
BEM+Sassでよく使う次の書き方は、Native CSS Nestingへそのまま持ち込めません。
.card {
&__title {
...
}
}
Native CSSの&は、Sassのように文字列を連結するためのものではなく、親ルールがマッチした要素を表すセレクタです。見た目は似ていますが、同じものではありません。
「ネストして整理する」という部分はCSS標準でもできるようになりました。ただし、Sassには関数、mixin、ファイル設計など別の役割があります。CSS NestingがあるからSassが不要になった、という話ではありません。
Sassで可変フォントサイズを扱う方法は、fluid()関数で可変フォントサイズをpx感覚のまま扱うでも整理しています。
そして2026年、textareaの自動リサイズまでCSSでできる field-sizing
最後は、ここまで紹介したCSSとは少し立場が違います。field-sizingは2026年6月にBaseline 2026の「Newly available」に入った、今回もっとも新しい機能です。古いブラウザやWebViewまで対象にする案件では対応状況の確認が必要ですが、「ここまでCSSでできるようになった」という例として紹介します。
お問い合わせフォームやチャットUIで、入力内容に合わせてtextareaの高さを自動的に伸ばしたいことがあります。
昔はJavaScriptで高さを計算していた
textarea.addEventListener('input', () => {
textarea.style.height = 'auto';
textarea.style.height = `${textarea.scrollHeight}px`;
});
今なら1行で書ける
textarea {
field-sizing: content;
}
実務では、入力内容が増え続けても無限に高さが伸びないように、最小・最大サイズを組み合わせることも考えられます。
textarea {
field-sizing: content;
min-height: 120px;
max-height: 400px;
}
2026年、また一つ「このためだけのJavaScript」を書かなくてよい場面が増えました。ただし、2026年に広く利用可能になったばかりの機能なので、すべての案件へ機械的に入れるのではなく、対象環境を確認して使うのが前提です。
新しいCSSだから使えばいい、ではない
ここまで紹介すると、「古い書き方は全部やめて、新しいCSSへ変えればいい」と見えるかもしれません。でも、実務ではそう単純ではありません。
実案件で確認したいこと
aspect-ratioのように今では自然に採用しやすいものもあれば、field-sizingのように対象環境を少し慎重に見たいものもあります。
「新しいから使う」のではなく、「今この案件で使うメリットがあるか」を判断する。そこは昔も今も変わらないと思います。
AIにコードを書かせる時代だからこそ、実装方法を知っておきたい
最近はAIに「固定ヘッダー分を考慮してスクロールさせて」「16:9の動画エリアを作って」「textareaを入力に合わせて伸ばして」と頼めば、コードそのものはすぐに出てきます。
とても便利ですが、AIが出したコードが動いているからといって、それが今のWeb制作で一番シンプルな方法とは限りません。
aspect-ratioで済むところにpaddingハックが使われているscroll-padding-topで済むところにスクロール位置調整用のJavaScriptがある- Container Queriesが合う場面で、配置場所ごとのmodifierが増えている
- 対象環境で使えるのに、CSSで済むUIへ追加のJavaScriptが入っている
だからAIにコードを書いてもらう時代になっても、「何ができるか」を知っていることは、むしろ重要になったと感じています。
すべてを自分でゼロから書くことより、「これはもっとシンプルにできないか」「この案件ならこちらの方法が合っている」と判断できること。その判断をAIへの指示にも反映できると、出てくるコードも自分の実装方針に近づいていきます。
まとめ|昔の苦労を知っていると、CSSの進化がよく分かる
今回紹介したのは、次の10個です。
今回紹介した便利なCSS 10選
scroll-padding-top/scroll-margin-top:has()aspect-ratioclamp()gapdvh/svh/lvh- Container Queries
subgrid- CSS Nesting
field-sizing
JavaScriptで位置を計算したり、HTMLへクラスを追加したり、paddingの割合を計算したり、最後の要素だけmarginを消したり。当時は普通に書いていたコードが、今ではCSS数行、場合によってはたった1行で済むようになっています。
昔の方法が間違っていたわけではありません。当時できなかったことを、CSS自身ができるようになった。そう考えると、この20年ほどでWeb制作がどれだけ変わってきたのかがよく分かります。
CSSは今も進化しています。長くWeb制作をしているからこそ、「これは昔こうやっていた」で止まらず、「今なら、もっとシンプルに書けないだろうか?」と、ときどき自分の中の常識を更新していきたいと思っています。
CSSの文字サイズ設計については、CSSのfont-size: 62.5%をやめたい。でも1rem=16pxに慣れない問題でも、昔からの書き方を見直す考え方を紹介しています。
Contact
CSS設計や実装方法も、
制作前に相談できます
KU NEL WEBLEでは、デザインだけでなく、HTML・CSSの設計や更新しやすさも含めてWebサイトを制作しています。
「今のCSSを整理したい」「古い実装を見直したい」「新しいCSSをどこまで使ってよいか相談したい」といった内容も、サイト全体の目的や運用方法に合わせて一緒に整理できます。
こんな整理をお手伝いできます
新規制作はもちろん、リニューアルや既存サイトの実装整理からでもお気軽にご相談ください。
Webサイト制作・リニューアルのご相談
見た目だけでなく、
更新しやすいWebサイトを制作します。
KU NEL WEBLEでは、デザイン・コーディング・WordPress実装・スマホ対応・アクセシビリティまで含めて、長く使いやすいWebサイト制作を行っています。新規制作やリニューアルをご検討中の方は、お気軽にご相談ください。
Webサイト制作・リニューアルのご相談
見た目だけでなく、
更新しやすいWebサイトを制作します。
KU NEL WEBLEでは、デザイン・コーディング・WordPress実装・スマホ対応・アクセシビリティまで含めて、長く使いやすいWebサイト制作を行っています。新規制作やリニューアルをご検討中の方は、お気軽にご相談ください。