要素の横並びをリキッドレイアウト(%単位)で、ネガティブマージンを使って実装する方法

  • 更新日:
  • 公開日:

ホームページを作っていると頻繁に行うデザイン「横並び」。これをリキッドレイアウト+ネガティブマージンで実装する内容です。

2014年10月23日追記:

以降で述べる計算をそのまま使ったWebツールを作ってみました。ちょっと使いづらいかもしれませんが、自分で計算するよりは楽だと思います。「Gridulator」と合わせて使うと捗りそうです。

紹介記事はこちらです。

px値での横並び方法

始めにpx値での横並びについて。この横並びには要素をインライン化する方法、floatする方法などがあります。どちらの方法を取るにしても、大体の場合は要素間にmarginで余白を設定しますよね。

この右、もしくは左に設定された余白をそのままにすると、親要素内に横並びにした子要素(の横幅)が収まらないので端っこがカラム落ちしてしまいます。

css-list-layout-negative-margin-01
divタグでulタグを囲っている図です。divタグに横幅320pxを指定しており、ulタグには横幅指定はありません

なので、これを解決する方法として「端の要素にマージンを0にするクラスを付ける」、「親要素にネガティブマージンを設定する」などがありますが、今回は後者のネガティブマージンを使います。はみ出た余白の分だけ、親要素のmarginにマイナスの値を設定してやると収まるようになります。打ち消すイメージですかね。

element-horizontal-negative-margin02
青が<li>のマージン、黄が<ul>のマージンです

例えばこんなHTMLを横並びにする場合、

<div class="list-box">
    <ul>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>

CSSはこのようになるでしょう。divタグには横幅を指定し、ulタグには横幅を指定しないようにします。

.list-box {
 overflow: hidden;
 *zoom: 1;
 width: 320px;
}

.list-box ul {
 margin: 0 -10px 0 0; //ネガティブマージン
 padding: 0;
}

.list-box li {
 float: left;
 width: 100px;
 height: 100px;
 margin: 0 10px 0 0;
 background: #000006;
}

この方法を使えば「marginを0にするクラスを用意して端っこの要素のみに付ける」といったことをしなくても横並びのレイアウトが実現できます。が、このネガティブマージンを使ったやり方をリキッドレイアウト(幅を「%」で指定する手法)で利用するには一工夫必要になります。

リキッドレイアウト(%単位)での横並び方法

リキッドレイアウトで使う「%」単位は相対単位のため、少しだけ計算をしなくてはいけません。まず、値を変換する計算方法についておさらいしてみましょう。

pxから%に変換する式は以下です。

子要素のサイズ(%) = 子要素のサイズ(px) ÷ 親要素のサイズ(px) × 100

見ての通り特定の値に変換したい場合は親要素のサイズ指定が必須になります。

それでは、先ほどのサイズを例に計算してみます。親要素が320pxの場合、横並びにした子要素の横幅(100px)を%値に変換する計算は以下になります。

31.25% = 100 / 320 * 100

320pxにおいての100pxは「31.25%」だと分かりました。ついでにマージンの値(10px)も計算します。

3.125% = 10 / 320 * 100

マージンの値は「3.125%」ですね。では、リキッドレイアウトにこの値を使ってネガティブマージンを設定してみます。その結果がこちらの画像です。

css-list-layout-negative-margin-03

…あれ、ネガティブマージンを設定したのにカラム落ちしてしまいました。何故なのでしょうか。

ネガティブマージンは要素の横幅を増やす

実はこのマイナス値を使ったネガティブマージン、設定した分だけ要素の横幅を増やしてしまうんです。(横幅を指定していない場合に限り)

1つ目のpx値では親要素に「-10px」のネガティブマージンを設定しているのでulのサイズは「320px + 10px = 330px」になっています。

2つ目の%値の「-3.125%」は320pxに於いて10pxとなるので、同じくulのサイズは「320px + 10px = 330px」となっています。

通常の「px」は絶対単位のため、親要素のサイズに影響をうけません。がしかし、先述したように「%」は相対単位のため、子要素は親要素のサイズに影響を受けます。

上記で計算した子要素の横幅「31.25%」は親要素が「320px」の場合のみ100pxになります。今回の例でネガティブマージンが設定された親要素は「330px」にサイズが増えているので、子要素のサイズ(31.25%)は

103.125px = 330px * 31.25%

となっています。実際のサイズより数px増えてしまっているのです。マージン(3.125%)も同様にサイズが増えています。

10.3125px = 330px * 3.125%

こうして計算してみると、横並びにした要素の横幅が親要素に収まらずにカラム落ちしてしまうのも納得ですね。

ネガティブマージンで増えた値を元に計算する

というワケで、親要素のサイズ「320px」を元に計算したのが間違っていたのでした。ネガティブマージンで増えたサイズ「330px」を基準に計算するとこの問題を解決できます。

では実際に計算してみましょう。子要素の横幅(100px)は

30.3% = 100 / 330 * 100

となります。マージンの値(10px)は

3.03% = 10 / 330 * 100

ですね。(小数点以下がどこまでも続くので0の値から切り捨てています。小数点以下の値はブラウザによって解釈が違うのですが、今回のテーマとは違うので置いておきます)

この値を設定した結果、こちらの画像のようになります。

css-list-layout-negative-margin-04'

問題なくリキッドレイアウトでもネガティブマージンを使った横並びを実装できました。実際の動作デモページを用意したので確認してみてください。

2014年9月3日追記:

ネガティブマージン&リキッドレイアウトでの横並びをやるとき、たまに自分で書いたこの記事を見返すのですが「あれ、これって分かりやすく書かれてるのかな」と疑問に思うことがあるのでまとめます。

まとめ

ネガティブマージン&リキッドレイアウトでの横並びを実装するときに%指定が必要なCSSプロパティは3つです。

  • 横並び要素の横幅
  • 横並び要素間の余白
  • 親要素のネガティブマージン値

この中で「横並び要素間の余白」と「親要素のネガティブマージン値」は基本的に同じなので、計算が必要なのは「横並び要素の横幅」と「横並び要素間の余白」の2つになります。

これら2つの式を以下に記します。(「横並び要素間の余白」は分かりやすいよう”余白”という文字に省略しています)

横並び要素の横幅[%] = 横並び要素の横幅[px] ÷ ( 親要素[px] + 余白[px] ) × 100 余白[%] = 余白[px] ÷ ( 親要素[px] + 余白[px] ) × 100

この計算で出た答えを「横並び要素の横幅」、「横並び要素間の余白」、「親要素のネガティブマージン値(マイナスの値)」に設定すると、任意のサイズでネガティブマージン&リキッドレイアウトでの横並びができます。


pxから%への変換計算が面倒だったり考えたくなかったりする場合は計算ツール「Really Quick Responsive Web Design Calculator」がオススメです。使い方は単純なので解説は必要ないかもしれませんが、一応紹介記事も書いてます。

書いた人

Symbol Mark

Ryoichi(しつ)

除菌ティッシュを買い込んで使いきれずによく乾かす人。

療養目的で退職し、どうやって生きていくか模索中。最近は勉強目的でLaravelやVue.js弄ったり、趣味で音で遊んでます。

※2019年10月16日現在ブログリニューアル中です。崩れなどが発生していたらすみません。

うぇぶ: @s_ryone