CSSで画像やブロックの幅を可変にする max-widthとmin-width

max-widthmin-widthは、CSS2.1から使えるようになった要素の最大/最小幅を指定するプロパティです。 CSS3の実装が進んだ現在は、PCとスマートフォンのほぼ全てのブラウザで利用可能です。

この記事では、レスポンシブデザインに欠かせない、widthを含めた3つのプロパティの関係と、可変幅の指定方法について解説します。

max-widthとmin-width

要素(画像やブロック)に対してmax-widthで表示する最大幅を、min-widthで最小幅を指定できます。 これらのプロパティを応用することで、ブラウザの幅に連動した要素幅の可変が実現できます。

なおページ全体の幅が固定であれば、通常通りwidthのみで幅を決定したほうが描画速度的に有利です。

幅指定の優先度

要素の幅を指定するCSSプロパティは、下記のように min-widthが最も優先されます。

min-width > max-width > width

これらを指定すると、実際に表示される幅(width)はmin-widthmax-widthの間の値に制限されます。
また、3つのうちでmin-widthに最も大きな幅を指定すると、max-widthwidthにどんな値を指定しても min-widthの幅で固定になります。

widthの100%とauto

widthの100%は、親ブロックの幅に対しての100%です。 その為、画像に100%を指定すると、画像本来の幅は無視されます。

画像にwidth: autoを指定すると、ブラウザにより画像本来の幅が設定されます。

画像幅を可変にする

レスポンシブデザインでは、画像の幅をブラウザ幅の変動に合わせて可変にしたい場合があります。 CSS2.1以降はそれを可能にする方法がいくつか有りますが、ブラウザ毎の実装状況の差も有り、現時点での選択肢は限られています。

概ね下記の何れかのような指定になるでしょう。

.A {
    width: 100%;
    max-width: 500px;
    min-width: 300px;
    height: auto;
}

.B {
    width: 500px;
    max-width: 100%;
    min-width: 300px;
    height: auto;
}

.C {
    width: auto;
    max-width: 100%;
    min-width: 300px;
    height: auto;
}

Awidth: 100%で画像の幅が親要素の幅に連動するようになります。 最大幅はmax-width、最小幅はmin-widthによって制限されますので、それぞれの値に達するとそれ以上変動せず、親要素の幅は無視されます。 論理的には最も明確と言えます。

Bでは、max-widthは100%ですが、最大でもwidthの幅を超えることは無く、widthより狭い時はmin-widthの幅になるまで連動します。結果的に、Aと同様の動作になります。

CもBと近い動作で、width: autoにより画像本来の幅が最大幅になる点だけが違います。 CSS側で最大幅を制限できない為、レスポンシブデザインとの相性はあまり良くありません。

BとCの場合、MDNの解説に拠れば max-widthwidthよりも優先するはずで、最大幅は親ブロックの内側の幅になりそうですが、親ブロックが充分に大きい場合でも実際にはそうなりません (Chrome, Firefox, Edgeの何れも)。
以上から、max-widthが100%の場合、最大幅はwidthの幅になると考えて良さそうです。

min-widthは何れも任意の最小幅を指定します。ここでは300pxとしています。

heightautoと指定してブラウザによる自動計算に任せます。これで、幅が変わった時でも画像本来の縦横比を維持したまま最適な高さになります。

確認環境

2017年3月時点のFirefox及びChrome最新版(Windows)で動作確認しました。
また、Chromeによるスマートフォンのエミュレーションでもテストしました。

参考URL

テーマ: HTML&スタイルシート(CSS) - ジャンル: コンピュータ

JavaScriptで配列の文字列をsuffix付きで連結

前回記事の応用で、複数の文字列の末尾に同じ文字列(suffix)を付けて連結する場合を考えてみます。

var array = ['#aaa', '#bbb'];
var string = array.join('_suffix, ') + '_suffix';

結果(string)
#aaa_suffix, #bbb_suffix

前回の応用ですから、これは簡単ですね。ついでに配列の各要素の前後に文字列を付ける場合も考えてみます。

var array = ['aaa', 'bbb'];
var string = '#' + array.join('_suffix, #') + '_suffix';

結果(string)
#aaa_suffix, #bbb_suffix

やや見苦しいですが(^_^;)ループ文を使わないで済みますので、これで良しとしましょう。
配列が不変ならば全て文字列で書いてしまったほうが早いですが、配列内容や要素数が不定だったり、後で追加する可能性がある場合にはこの方法が便利です。

テーマ: プログラミング - ジャンル: コンピュータ

JavaScriptで配列の文字列をprefix付きで連結

配列にある複数の文字列の頭に同じ文字列(prefix)を付けて連結したい事が時々あります。jQueryオブジェクトを複数のクラス指定で作りたい場合などです。
もちろんforやforEachを使えば可能な事なのですが、やりたい事の割に記述が冗長すぎる気がしたので、他の方法はないか考えてみました。
結論から言えば、完璧ではないものの可能です。

JavaScriptでの文字列の連結はjoin()で行えます。これはPHPのimplode関数や、Perlのjoin関数に相当するメソッドです。
join()は区切り文字を挟んで連結することは出来ますが、これだけではprefixは付けられません。

var array = ['aaa', 'bbb'];
var string = array.join(',');

結果(string)
aaa,bbb

それならば、頭に空文字列の要素を追加してprefix込みの区切り文字で連結すればいけるんじゃないかな?と考えたのが次の例です。concat()で空文字列と配列を連結した後、prefix込みでjoin()して、最後に頭の不要な文字を消去してます。

var string = [''].concat(array).join(',.prefix_').slice(1);

結果(string)
.prefix_aaa,.prefix_bbb

できた( ー`дー´)キリッ
…いや、できたことはできたのですが、何をやってるか少し分かり難いし、slice()でのカットは区切り文字の文字数に依存するので余り宜しくない。
うーん、と考えた結果、最終的にこれに落ち着きました。

var string = '.prefix_' + array.join(', .prefix_');

結果(string)
.prefix_aaa, .prefix_bbb

できた(`・ω・´)シャキーン
同じprefixを2箇所指定しないといけない為、記述の美しさの点では劣りますが、文字数や要素が少なく済み、見通しが良いのが利点です。やってることが単純なので、処理も速いことでしょう。
jQueryオブジェクトにしたい場合は下記のように$()で囲ってしまえば、余計な変数も作らずに済みます。

var obj = $('.prefix_' + array.join(', .prefix_'));

関連記事
JavaScriptで配列の文字列をsuffix付きで連結

テーマ: webサイト作成 - ジャンル: コンピュータ

line-heightの単位はemではない

line-heightの単位としてemを使うのは実は良くなくて、単位なしで指定するのが正解。

line-height - CSS | MDN より引用

パーセンテージ と em 値は、予期しない結果を生むかもしれません。

使用値は、この単位のない <数量> に要素のフォントサイズを掛けたものになります。計算値は、指定された <number> と同じです。ほとんどの場合、継承時の予期しない結果を避けるために、これが line-height をセットする好ましい方法です。


line-heightはフォントサイズを基準として掛け合わされる数値なので、単位を付ける必要はない。
むしろ単位をつけると継承に問題が生じる。

ずっとem付けてたけど、間違いだったとは…。
単位なしで指定してるのを見かけても、つけ忘れてるんだと思ってました(*ノω・*)

テーマ: HTML - ジャンル: コンピュータ

Scssの変数をcalcで使う

最新のCSS3の calc()は、動的な計算ができる便利な関数だ。
一方、Scss(sass)の変数と計算式では静的な計算しかできない為、これらを組み合わせて使いたい時がある。
例えば次のような場合。

$m: 10px;
width: calc(100% - ($m * 2));
margin: 0 $m;


一見これは上手く行きそうだが、出力結果はこうなってしまう。

width: calc(100% - ($m * 2));
margin: 0 10px;


(´・ω・`)…
そこで、インターポレーションを使って、こうする。

width: calc(100% - #{$m*2});

結果は、

width: calc(100% - 20px);

ブラボー!Scss+calcって素晴らしいですね(`・ω・´)
もっともこの例だと width: auto;でも良いんですけどね!

テーマ: HTML - ジャンル: コンピュータ