CSSの「calc()関数」を使ったレスポンシブ対応のレイアウトで高さを最適化するテクニック
Post on:2018年11月14日
レスポンシブ対応のレイアウトを実装する際に手間なのは、ブレイクポイントの定義です。ここ1,2年でもたくさんのデバイスがリリースされ、それに伴いスクリーンサイズの種類も増えてきました。
そんな時に便利なのがCSSの「calc()関数」を使ったテクニック。
calc()を使用して、デスクトップやタブレットやスマホのそれぞれに最適なレイアウトを実装するテクニックを紹介します。
Use calc() to Change the Height of a Hero Component
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- calc()を使ったフォントサイズの可変
- paddingとline-heightの場合
- ヒーローコンポーネントの場合
- calc()を使ったヒーローコンポーネントの実装
- calc()のサポートブラウザ
- 最後に
calc()を使ったフォントサイズの可変
表示されるスクリーンのサイズに合わせてフォントを最適なサイズに変更するテクニック(Fluid Typography)は、2年程前に登場しました。簡単に説明すると、2つのサイズが異なるビューポートでフォントサイズを定義し、その間のサイズ調整は自動的に行うというアイデアです。
これを実現するには、CSSのcalc()関数が登場するまでは、FitTextのようなjQueryのプラグインが必要でした。calc()関数を使用すると、下記のように簡単に実装できます。
1 2 3 |
p { font-size: calc(16px + (24 - 16)*(100vw - 400px)/(800 - 400)); } |
実際の動作は、下記でご覧ください。
スクリーンの幅を変更すると、フォントのサイズもそれに応じて変化します。
See the Pen Fluid Typography by Martino Stenta (@martinostenta) on CodePen.
ここで重要な数字は2つのサイズが異なるビューポートに定義した「24px」と「16px」です。フォントサイズは、800pxのビューポートでは24pxまで大きくなり、400pxのビューポートでは16pxまで小さくなります。
私はフォントのサイズやビューポートを定義する際に「最小(minimum)」または「最大(maximum)」という用語を使用しません。この用語は少し誤解を招くからです。実際には、400pxより小さい、800pxより大きいビューポートでデフォルトのフォントサイズを指定する必要があります。そうしないと、同じスケールでフォントが小さくなります(または大きくなります)。あるいは、より大きなサイズのスクリーンのために別のスケールを定義する必要があります。
See the Pen Fluid Typography with reset size by Martino Stenta (@martinostenta) on CodePen.
このテクニックはレスポンシブ対応時に、よく機能します。
ここで使用している数学は、非常に有用です。
paddingとline-heightの場合
私はこのFluid Typographyのコンセプトが気に入っており、他のプロパティでも機能するか考えてみました。%を使用することはできませんが、px, em, remの単位を使用する限り、問題はありません。私はpxを使用するので、もし他の単位を使用する時はFluid-responsive font-size calculatorで変換してください。
paddingとline-heightにcalc()関数を使用すると、定義されたスクリーンサイズに対して固定値の完全な流体レイアウトを実現できます。
スクリーンサイズに対して変化する値
まずは、デモを見てください。
See the Pen Pure CSS Variable Padding, Font Size and Line Height by Martino Stenta (@martinostenta) on CodePen.
Musiculturaでこのテクニックをfont-sizeだけでなく、line-heightとpaddingにも採用し、非常によく機能しています。数学を使用すると、実装が簡単になります。
See the Pen Working Example of calc() on font-size and line-hieght by Martino Stenta (@martinostenta) on CodePen.
ヒーローコンポーネントの場合
私はこのテクニックをヒーローコンポーネントにも利用できないものか、と考えました。ヒーローコンポーネントはBootstrapをはじめとするデザインシステムで定番となり、現在では多くのサイトで利用されています。
ヒーローコンポーネント
私の主な悩みは、このヒーローコンポーネントをレスポンシブ対応にする最善の方法に関係しています。ヒーローコンポーネントがフルスクリーンではない場合(つまり任意のサイズのビューポートで)、通常はその挙動をデザイナーに尋ねるでしょう。
多くの場合、内部の要素を配置する際に%でpadding-bottomを使用することで、うまく機能します。特に、デスクトップ版のサイトでうまく機能します。
See the Pen Standard hero section with 'padding-bottom' by Martino Stenta (@martinostenta) on CodePen.
しかし、タブレットやスマホのようにビューポートを縮めるとどうなるでしょうか?
ある程度までは読みやすいままですが、比率を変更する必要があります。
レスポンシブ対応に実装する際にデスクトップを優先すると、小さなスクリーンでは縦長の四角形になるポイントまで横長の四角形が縮小することになります。
デバイスに基づいて異なる比率のヒーローコンポーネント
これが悩みの種です。なぜなら、さまざまなブレークポイントに最適化されたヒーローコンポーネントを実装するためには、多くのCSSを必要とするからです。
もっと良い解決方法が必要です。そうではありませんか? ページの幅が狭くなっている時に、ヒーローの高さを増やすことができたらどうでしょうか?
calc()を使ったヒーローコンポーネントの実装
このレイアウトを数学的に処理させ、ビューポートが変更された時に応じて処理ができるcalc()関数の登場です。
Fluid Typographyで使用したコードがあります。
1 2 3 4 5 6 7 8 9 |
p { width: 100%; max-width: 1200px; margin: 0 auto; font-family: 'Open Sans', sans-serif; font-size: calc(24px + (18 - 24)*(100vw - 400px)/(1200 - 400)); line-height: 1.5; padding: 10px; } |
このコードに解決する方法があります。ページの幅が狭くなっている時に、ヒーローコンポーネントがより大きくなります。流体部分の単位には、pxを使用しています。
スクリーンサイズに対してのpadding-bottomの値
コードにすると、下記のようになります。
1 2 3 |
.hero { padding-bottom: calc(600px + (300 - 600) * (100vw - 600px) / (1200 - 600)); } |
実際の動作は、下記のデモをご覧ください。
See the Pen Pure CSS Variable Padding Bottom by Martino Stenta (@martinostenta) on CodePen.
ヒーローコンポーネントの高さは期待通りに、スムーズに移行します。
スクリーンサイズに対して変化するヒーローコンポーネントの高さ
このテクニックは、テキストに対して垂直スペースを与える時にも非常に便利です。
ビューポートの幅を狭くすると、テキストの行が増えますが、これはフォントサイズを小さくすることはできないためです。
テキストの上に垂直スペース
実際の動作は、下記のデモでご覧ください。
See the Pen Hero section with calc() by Martino Stenta (@martinostenta) on CodePen.
calc()はfont-size以外にも問題を解決できる優れた機能であることが証明されました。
calc()のサポートブラウザ
calc()は、現在Opera miniを除くすべてのブラウザにサポートされています。これは非常に素晴らしいことです。
ただし、calc()を使用したこのテクニックでは、px, em, remの単位しかサポートしていないことに注意してください。しかし、ヒーローコンポーネントの幅は通常100%であるため、padding-bottomのように単位を%からpxに変換するのはかなり簡単です。
また、calc()関数のブレークポイントの前後で値をリセットすることを忘れないでください。そうしないと、ターゲットプロパティの値が大きい、あるいは小さい値になります。
最後に
ここで紹介したテクニックはレイアウトの問題を解決するための単なる方法で、calc()関数に対する好奇心によって引き起こされました。
最後に質問をします。
あなたはヒーローコンポーネントの高さをどのようにスケーリングしますか? そのためにcalc()を使用しますか? さまざまな幅用にブレークポイントを用意するのを好みますか? あなたが使用している何か他の方法はありますか?
sponsors