widthが効かない時に考えるべき20の実例付きチェックリスト

CSS Widthが効かない問題を解決する方法を学ぶCSS
この記事は約34分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●widthが効かない時に確認すべき20のポイント

CSSでWebサイトのレイアウトを作る時、widthプロパティはとても重要な役割を果たします。

ボックスの幅を思い通りにコントロールできれば、見栄えの良いデザインに仕上げられるでしょう。

しかし、思った通りの幅にならず困ってしまったことはありませんか?

実は、widthが効かない原因はたくさんあるんです。ちょっとしたミスや勘違いが積み重なって、イメージ通りにならないなんてよくある話。

でも大丈夫、ここではそんなwidthが効かない時に確認すべき20のポイントを詳しく解説していきます。

一緒にレイアウトのお悩みを解決していきましょう!

○widthを指定する要素は正しいか

まず最初に確認したいのが、widthを指定する要素が正しいかどうかです。

HTMLの構造をよく見て、本当にスタイルを適用したい要素を選択できているでしょうか。

例えば、 divのつもりがpやspanになっていたり、 classやidの指定を間違えていたりすると、意図しない結果になってしまいます。

セレクタに誤りがないか、今一度コードを見直してみるのが賢明ですね。

間違いに気付けたら、すぐに修正を。

○親要素のwidthは指定されているか

実は、子要素のwidthは親要素に大きく依存しているんです。

例えるなら、親からもらったお小遣いの範囲内でしかお買い物できない子供のようなもの。

つまり、親要素の幅が制限されていれば、子要素の幅もその制限を受けます。

%. emなどの相対値で指定していると、予想外の幅になる可能性大。

親のwidthを具体的なピクセル値で指定するのがセオリーですね。

親子関係をしっかり意識すれば、ほとんどのケースでは解決への近道になるはず。

でも、時にはもっと根の深い原因が潜んでいることもあります。

○CSSの優先順位は正しいか

実はCSSには「優先順位」というルールがあって、同じプロパティが複数回指定されていると、優先度の高い方が採用されるんです。

これを「詳細度」とも言います。

!importantを筆頭に、要素への直接指定、idセレクタ、classセレクタ、要素セレクタの順に優先度が下がっていきます。

それぞれの詳細度の数値を比べて、一番大きい方が勝つという仕組み。

意図せずに優先度の高いwidthが指定されてしまっていると、本来適用したいスタイルが負けてしまうんですよね。

CSSのカスケーディングルールを理解して、意図した通りの詳細度になるようにコードを書き換えましょう。

○widthの値は正しいか

さて、優先順位の話に続いて、次に確認すべきはwidthの値そのものです。どんな風に書いてあるか、もう一度コードを見つめ直してみましょう。

例えば、こんなミスはありませんか?

  • 数値だけ書いてあって単位を書き忘れている
  • %を書くつもりが、pxと間違えている
  • プラスの値のつもりが、マイナスになっている

ちょっとした記述ミスが、思わぬ結果を招くことも。

細心の注意を払って、正しい値が設定されているか確かめましょう。

数値だけでなく、autoやinitial、inheritといったキーワードにも要注意。それぞれ役割が違うので、意図に合ったものを選ぶ必要があります。

使い分けを理解して、状況に応じた適切な値を設定するのがポイントです。

○単位は正しいか

値と同様に、単位の指定も間違えやすいポイントの一つ。

widthではpxやem、%などをよく使いますが、それぞれの特性を理解しておかないと思わぬ落とし穴にはまってしまうかもしれません。

例えば、%は親要素に対する割合を表します。

つまり、親のwidthが変われば、それに合わせて子要素の幅も変化するということ。

レスポンシブデザインではよく使われる単位ですが、固定幅を作りたい時には不向きですね。

一方、pxは絶対値を表すので、どんな環境でも一定の幅を保てます。

ただ、あまりに大きな値を指定するとはみ出てしまうので、max-widthと組み合わせるのが賢明。

そうすれば、どんな画面サイズでも見やすく収まるレイアウトになるでしょう。

○max-widthやmin-widthが影響していないか

そう、max-widthとmin-widthはwidthと一緒に使うことで、より柔軟なレイアウトが実現できるんです。

前者は最大幅を、後者は最小幅を指定するためのプロパティ。

widthの値をある程度制限してくれるので、状況に合わせて活用しましょう。

ただし、max-widthはwidthより優先度が高いので、widthの値を上書きしてしまうことも。

意図しない結果になっている場合は、max-widthの値を見直してみるのがいいかもしれません。

min-widthは逆に、指定した値より小さくならないように制限をかけてくれます。

コンテンツを詰め込みすぎて潰れてしまうのを防ぐのに役立つプロパティですね。

でも、max-widthもmin-widthも、使い方を誤ると逆効果になってしまうことも。

バランス感覚を持って適切に設定することが肝心です。

○box-sizingの設定は適切か

ここまでの話を聞いて、「あれ?width効かないのはボックスモデルのせいかも?」と思った方、鋭いですね!

実はその通り、box-sizingの設定が影を落としているケースはとても多いんです。

デフォルトのcontent-boxでは、widthはコンテンツ領域の幅を表します。

つまり、borderやpaddingを指定すると、トータルの幅はwidthより大きくなってしまうということ。

これが意図しないレイアウト崩れの原因になることも。

そんな時はbox-sizingをborder-boxに設定するのが正解。

これなら、borderやpaddingを含めてちょうどwidthで指定した幅になるので、予測しやすいレイアウトが組めます。

どのボックスにもまずはこの設定から始めると良いでしょう。

○displayプロパティの値は適切か

ボックスモデルの話が出たところで、次に注目したいのがdisplayプロパティです。

実はこれ、widthと深~い関係があるんですよ。

displayの値によって、要素の表示方法が大きく変わります。

例えばblockなら、要素が横幅いっぱいに広がるブロックレベル要素として扱われ、widthで幅を指定できるようになります。

一方、inlineなら要素はインライン要素として振る舞い、widthは無視されてしまうんです。

デフォルトがblockではない要素、例えばspanやaなどにwidthを指定しても効かないのは、実はこのdisplayの値が関係しているんですね。

意図通りにwidthを適用したいなら、まずはdisplayをblockに変更することから始めましょう。

でも、これで問題が全て解決するわけではありません。

今度はレイアウトの方式によって、widthの効き方が変わってくるんです。

次は、そんな落とし穴についてお話ししますね。

○positionプロパティが影響していないか

CSS初心者の頃、positionの存在に気付いた時はとてもワクワクしたものです。

absoluteやfixedを使えば、自由自在に要素を配置できる!…と思ったのも束の間、思うようにwidthが効かなくて頭を抱えた経験、ありませんか?

実は、positionの値によってもwidthの解釈は変化します。

特にabsoluteやfixedを指定すると、要素はフロートと同じように、インライン要素のような振る舞いをするんです。

つまり、widthを指定しないとコンテンツの幅に応じて伸び縮みし、100%と指定すると逆に親要素いっぱいに広がってしまうということ。

これはpositionの特性上、仕方のないことなんですが、知らないとハマるポイント。a

bsoluteやfixedで配置した要素のwidthがうまく効かない時は、明示的に幅を指定することを忘れずに。

○flexboxレイアウトを使っていないか

さて、ここからはいよいよモダンなレイアウト手法の登場です。

flexboxは、CSSでフレキシブルなレイアウトを組むための強力な武器。

でも、その特殊な動作ゆえに、widthとはちょっと相性が悪かったりするんですよね。

flexboxでは、親要素のdisplayにflexを指定することで、その直下の子要素がフレックスアイテムになります。で、面白いのはここから。

フレックスアイテムに指定したwidthは、「最大値」のような扱いになるんです。

つまり、コンテンツがwidthより小さければ、実際の幅はコンテンツに応じて縮むし、コンテンツがwidthを超えていれば、みんな等分に伸びて親の幅いっぱいに並ぶ、と。

flexboxの基本動作に則った振る舞いなんですが、widthをガチガチに固定したい時には邪魔になるかも。

そんな時は、 flex-growflex-shrinkflex-basisといったプロパティを駆使して、理想のサイズ感を追求しましょう。

○tableレイアウトを使っていないか

flexboxに続いて、もう一つのテーブルレイアウトに注目です。

HTMLのtable要素を使ったレイアウトは、昔はよく見かけましたが、今ではあまり推奨されていません。

でも、tableの特性上、widthが思った通りに効かないことがあるんですよね。

tableの各列の幅は、デフォルトではコンテンツに応じて自動的に決まります。

つまり、th要素やtd要素にwidthを指定しても、それはあくまで「最小幅」として扱われ、コンテンツが多ければ勝手に広がってしまうということ。

これを防ぐには、tableやcolグループにtable-layout: fixedを指定するのが一般的。

こうすれば、各列の幅は最初の行のセルを基準に固定されるので、より制御しやすくなります。

ただし、固定レイアウトにすると、コンテンツがセルからはみ出す可能性もあるので、その点は要注意ですね。

できるだけ、tableはテーブルデータを表示する目的でのみ使い、レイアウトにはdivなどの汎用的な要素を使うのがベターです。

そうすれば、widthのコントロールもしやすくなるはずですよ。

○CSSのセレクタは正しいか

ここまでは主にプロパティの話をしてきましたが、セレクタの選び方もwidthに大きく影響します。

単純に要素名を指定するだけでは、意図しないところまでスタイルが適用されてしまうこともあるんです。

そんな時は、classやidを活用するのが一般的。

例えば、あるdivにだけ特別な幅を指定したいなら、そのdivにクラス名を付けて、そのクラスをセレクタにするのが手っ取り早いでしょう。

これなら、ほかのdivには影響せずに済みます。

セレクタの書き方にもコツがあって、詳細度を意識することが大切。

詳細度が高いほど優先されるので、詳細度の低いセレクタで指定したwidthが、詳細度の高いセレクタで上書きされてしまうことがあるんですよね。

理想は、詳細度を低く保ちつつ、適切な粒度でスタイルを当てていくこと。

そのためには、HTMLの構造をよく理解して、セレクタを適切に選ぶ必要があります。

これは、widthに限らずCSSを書く上で常に意識したいポイントですね。

○スタイルシートは正しく読み込めているか

さて、いくら頑張ってwidthを指定しても、そもそもスタイルシートが正しく読み込めていなければ意味がありません。

ブラウザのデベロッパーツールを使って、CSSが適用されているかどうかをチェックしましょう。

もし、スタイルシートが反映されていないようなら、まずはlink要素やstyle要素の記述が正しいか確認を。

パスの指定ミスなどがあると、せっかく書いたCSSが機能しないので要注意です。

また、HTMLファイルとCSSファイルの文字コードが異なっていると、文字化けが起きてスタイルが適用されないこともあります。

両者のエンコーディングを統一することを忘れずに。

スタイルシートが正しく読み込めるかどうかは、widthに限らずCSSの基本中の基本。

HTMLとCSSをつなぐ重要な部分なので、今後トラブルが起きたらまずはここをチェックしてみると良いでしょう。

○CSSのメディアクエリは正しいか

スマホやタブレットなどのモバイルデバイスが普及した今、レスポンシブWebデザインは必須の技術。

そして、レスポンシブレイアウトを実現する上で欠かせないのが、メディアクエリです。

メディアクエリを使えば、画面の幅に応じて異なるスタイルを適用できます。

例えば、PCサイズの画面では3カラムだったレイアウトを、スマホサイズではシングルカラムに変更する、といった具合。

これなら、どんなデバイスでも見やすく使いやすいサイトが作れるでしょう。

ただし、メディアクエリの記述を間違えると、思った通りのレイアウトにならないことも。

特に、min-widthとmax-widthの使い分けや、ブレイクポイントの設定には注意が必要です。

また、メディアクエリでwidthを指定する時は、優先順位にも気を付けましょう。

メディアクエリ内のスタイルは、通常のスタイルよりも優先度が高いので、意図しない上書きが起きる可能性があるんです。

理想のレスポンシブデザインを実現するには、メディアクエリをマスターすることが不可欠。

デバイスの多様化が進む中、これからますます重要になるスキルだと言えるでしょう。

○ベンダープレフィックスは必要か

メディアクエリの話が出たところで、もう一つ忘れてはいけないのが、ベンダープレフィックスです。

ベンダープレフィックスとは、ブラウザ独自の実験的な機能を使う時に付ける接頭辞のこと。

主要ブラウザにはそれぞれ固有のプレフィックスがあって、例えばWebkitはSafari、ChromeなどのWebKitベースのブラウザで使われています。

新しいCSSプロパティは、正式にW3Cの仕様になる前から、ベンダープレフィックス付きで実装されることがあります。

そのため、先端的なレイアウトを試みる時は、ベンダープレフィックスが必要になることも。

でも、ここで落とし穴があるんです。

例えば、flexboxの初期の頃は、ベンダープレフィックス付きのプロパティが主流でした。

でも、仕様の変更に伴って、プレフィックス無しが標準になり、今ではプレフィックス付きは非推奨になっています。

こうした移り変わりを知らないと、古い記述が混在して、widthの効き方がおかしくなることも。

ベンダープレフィックスを使う時は、ブラウザの対応状況をこまめにチェックすることが大切。

Can I useなどの対応表を参考にしながら、必要最小限のプレフィックスに絞るのがおすすめです。

○CSSのリセットやノーマライズが影響していないか

CSSを書く時、ブラウザのデフォルトスタイルをリセットするのは常套手段。

でも、その方法によっては、widthの効き方に影響が出ることがあるんです。

例えば、リセットCSSの中には* { margin: 0; padding: 0; }のように、ユニバーサルセレクタを使って全要素のマージンとパディングを0にするものがあります。

これは一見便利そうですが、実はwidthの計算にも影響します。

box-sizingの初期値はcontent-boxなので、width: 100%;を指定しても、ボーダーやパディングが加わって100%を超えてしまうことが。

そんな時は、ユニバーサルセレクタは避けて、本当に必要な要素だけをリセットするのがおすすめ。

あるいは、Eric MeyerのReset CSSのように、box-sizingをborder-boxにするのも一案です。

また最近は、ノーマライズCSSという手法も注目されています。

これは、ブラウザ間の差異を吸収しつつ、有用なデフォルトは残すというもの。

margin: 0;などの大胆なリセットは避け、より穏やかに初期化するのが特徴。

widthの計算にも優しいので、モダンな開発には良く馴染むでしょう。

○CSSのカスケーディングを理解しているか

CSSのカスケーディングルールは、スタイルシートの根幹をなす重要な概念。

でも、意外と奥が深くて、きちんと理解している人は少ないかもしれません。

カスケーディングとは、複数のスタイルシートや宣言が競合した時に、どれが優先されるかを決める仕組みのこと。

詳細度、ソースの順序、重要度の3つの基準に基づいて、適用されるスタイルが決まります。

例えば、idセレクタはclassセレクタより詳細度が高いので、そこで指定したwidthが優先されます。

!importantは最優先されるので、これが付いていると他の宣言は全て上書きされてしまう。

でも、これを乱用すると、カスケーディングの利点が失われてメンテナンス性が下がるので注意が必要ですね。

また、同じ詳細度の宣言が競合した場合は、後に書かれた方が優先されます。

これを逆手に取って、意図的に順序を入れ替えることで、widthの値を調整することもできるんです。

カスケーディングをマスターすれば、CSSの悩ましい競合も、より戦略的に解決できるようになるはず。コツは、HTMの構造とセレクタの詳細度をよく見極めること。

そうすれば、どの宣言が勝つのか、widthがどう決まるのかが見えてくるでしょう。

○CSSの詳細度を理解しているか

ここで、カスケーディングの中でも特に重要な、詳細度について深掘りしてみましょう。

詳細度は、セレクタの種類によって決まる数値。

idセレクタは100、classセレクタは10、要素セレクタは1というように、セレクタごとにポイントが割り振られています。

そして、セレクタを組み合わせた時は、そのポイントを足し算して詳細度を算出するんです。

例えば、#header .logoなら、idセレクタとclassセレクタの組み合わせなので、100+10で詳細度は110。一方、.header .logoなら、classセレクタが2つなので10+10で20。

つまり、#header .logoの方が.header .logoより詳細度が高いということ。

同じ要素に対して、詳細度の異なる宣言が競合した時は、常に詳細度の高い方が勝ちます。

だから、idセレクタで指定したwidthは、classセレクタのwidthより優先されるわけです。

詳細度の仕組みを理解すれば、より的確にセレクタを選べるようになります。

できるだけ詳細度を低く抑えつつ、適切な粒度でスタイルを当てるのがベスト。

理想をいえば、要素セレクタとclassセレクタをメインに使い、idセレクタは必要最小限にとどめるのが賢明でしょう。

そうすることで、カスケーディングがより柔軟に機能し、メンテナンス性の高いCSSが書けるはずです。

もしwidthがうまく効かない時は、セレクタの詳細度を見直してみるのも一案かもしれませんね。

○ブラウザの互換性は大丈夫か

最後に、忘れてはいけないのがブラウザの互換性チェックです。

世の中には古いブラウザもまだまだ現役。

せっかく書いたCSSが、そういうブラウザで全く効かなかったら台無しですからね。

widthに関しては、比較的どのブラウザでも安定して使えるプロパティではあります。

でも、flexboxやgridなど、モダンなレイアウト手法となると、ブラウザ対応がまだら模様。

これを使う際は、念のため Can I useなどでチェックしておくと安心です。

また、モバイル端末の普及に伴い、Safariや Android Browser、Chrome for Android などのモバイルブラウザにも目を配る必要があります。

デスクトップ版とは挙動が微妙に異なることがあるので、実機でのチェックが欠かせません。

理想をいえば、メジャーなブラウザは全てカバーしたいところ。

でも、現実的に全てに対応するのは難しいですよね。

そんな時は、ターゲットとするユーザー層を考えて、そこで多く使われているブラウザを重点的にチェックするのがおすすめ。

例えば、若年層をターゲットにしたサイトなら、最新のブラウザが中心になるでしょう。

一方、シニア層も視野に入れるなら、Internet Explorerなどの古いブラウザにも配慮が必要かもしれません。

いずれにせよ、「このブラウザなら大丈夫だろう」と決めつけるのは禁物。

実際に確かめてみないと、widthの効き方は分からないのです。

地道な検証を重ねることが、より堅牢なWebサイトへの近道になるはずです。

●widthが効かない時のサンプルコードと解説

さて、ここまでwidthが効かない原因を色々と見てきましたが、実際のコードを見てみないと、具体的なイメージがつかみづらいですよね。

そこで、これからはサンプルコードを交えながら、より実践的な解決方法を探っていきましょう。

○サンプルコード1:親要素のwidthを指定する

まず、親要素のwidthが指定されていないことが原因のパターンから。

<div class="parent">
  <div class="child">
    コンテンツ
  </div>
</div>
.child {
  width: 50%; /* 効かない! */
}

このコードでは、.childに50%のwidthを指定していますが、親の.parentにはwidthがありません。

この状態では、子の幅は親に対する割合で決められないので、50%が効きません。

これを解決するには、.parentにwidthを指定するのが一番の近道。

.parent {
  width: 800px;
}

.child {
  width: 50%; /* 効く! */
}

これで、.childは.parentの幅の50%、つまり400pxになります。

%を使う時は、親のサイズが決まっていることが大前提だということを忘れずに。

○サンプルコード2:max-widthの影響を排除する

次は、max-widthが邪魔をしている例です。

<div class="box">
  コンテンツ
</div>
.box {
  max-width: 600px;
  width: 100%; /* 効かない! */
}

ここでは、.boxに max-width: 600px;width: 100%; を両方指定しています。

この場合、max-widthが優先されるので、widthは600pxまでしか広がりません。

100%にはならないんです。

max-widthを使いつつ、widthも思い通りに効かせるなら、こんな風に書き換えるのがおすすめ。

.box {
  width: 100%;
  max-width: 600px; /* 上書きする */
}

このように、max-widthをwidthより後に書けば、widthが先に適用されて100%になった後に、max-widthで上限が設定されます。

つまり、画面サイズが600pxより広ければ100%、狭ければ600pxに収まる、という具合ですね。

カスケーディングルールをうまく活用することで、一見相反するプロパティも共存できるようになる。

こういったテクニックを知っておくと、レスポンシブデザイン時に特に役立つはずです。

○サンプルコード3:box-sizingの設定を見直す

box-sizingの話は前章で触れましたが、改めてコードで見てみましょう。

<div class="container">
  コンテンツ
</div>
.container {
  width: 100%;
  padding: 20px;
  border: 10px solid black;
  /* はみ出る! */
}

width: 100%に加えて、paddingとborderを指定すると、トータルの幅がその分だけ大きくなってしまいます。

つまり、はみ出る原因になります。

この問題は、box-sizingをborder-boxに変更すれば一発解決。

.container {
  box-sizing: border-box;
  width: 100%;
  padding: 20px;
  border: 10px solid black;
  /* ピッタリ収まる! */
}

border-boxを指定すれば、widthにpaddingとborderが含まれるようになるので、トータルの幅は100%を超えません。

逆に、100%ピッタリに収めたい時に、とても便利な手法だと言えるでしょう。

box-sizingはレイアウトに大きく影響するプロパティなので、余白の調整でwidthがうまく効かない時は、真っ先にチェックしたい項目の一つ。

border-boxをデフォルトにしておけば、このような悩みともおさらばできるかもしれませんね。

○サンプルコード4:displayプロパティの値を変更する

displayの話は少し複雑に感じるかもしれませんが、実際のコードを見れば意外とシンプル。

まずは、こんなHTMLを考えてみましょう。

<span class="inline-block">
  インラインブロック要素
</span>

ここに、こんなCSSを適用するとします。

.inline-block {
  width: 200px; /* 効かない! */
}

spanはインライン要素なので、widthを指定しても効きません。

この状態では、コンテンツの幅に合わせて自動的にサイズが決まるんですよね。

インライン要素にwidthを効かせるには、displayの値を変更するのが一番手っ取り早い解決策です。

.inline-block {
  display: inline-block;
  width: 200px; /* 効く! */
}

これで、spanがインラインブロック要素になりました。

インラインブロック要素なら、widthが使えるので、思い通りの幅を指定できるというわけです。

displayを使いこなすコツは、各値の特性をしっかり理解すること。

blockなら縦に積まれ、inlineなら横に並ぶ。inline-blockなら、インラインの流れを保ちつつブロックレベルのプロパティが使える、と。

状況に応じて使い分けられるようになると、レイアウトの自由度がぐんと広がりますよ。

○サンプルコード5:flexboxレイアウトで幅を調整する

flexboxは、モダンなレイアウトには欠かせない機能。

でも、独特の仕様ゆえに、widthとの兼ね合いで悩むこともありますよね。

<div class="flexbox">
  <div class="item">アイテム1</div>
  <div class="item">アイテム2</div>
  <div class="item">アイテム3</div>
</div>
.flexbox {
  display: flex;
}

.item {
  width: 200px; /* 効かない! */
}

このコードでは、.flexboxの子要素である.itemにそれぞれ200pxのwidthを指定していますが、実際にはそれより大きく伸びてしまうかもしれません。

これはflexboxの標準動作で、親の幅に合わせて子要素が自動的にサイズ調整されるためです。

特に、.itemの幅の合計が.flexboxを超える場合、flex-shrinkが働いて、各アイテムが均等に縮小されます。

この時、200pxというwidthは「最大値」のような扱いになるんですね。

これを回避するには、flex-shrinkを0にするのが手っ取り早い解決策。

.flexbox {
  display: flex;
}

.item {
  flex-shrink: 0;
  width: 200px; /* 効く! */
}

flex-shrink: 0;を指定すれば、アイテムは絶対に縮小されなくなります。

つまり、widthで指定した値がそのまま適用される、と。

ただし、この方法だと合計幅が親を超えた時に、アイテムがはみ出してしまうので注意が必要。

理想を言えば、各アイテムの幅を%で指定して、flex-growとflex-basisを適切に設定するのがベストですね。

柔軟な伸縮を実現しつつ、アイテム同士のバランスも取れるはずです。

○サンプルコード6:tableレイアウトでwidthを指定する

最後は、tableレイアウトでのwidthの指定方法を見ていきましょう。

<table>
  <tr>
    <td>セル1</td>
    <td>セル2</td>
  </tr>
</table>
td {
  width: 200px; /* 効かない! */
}

このように、tdにwidthを指定しても、それは最小幅としてしか扱われません。

コンテンツが多ければ、セルは自動的に広がってしまうんですよね。

これを防ぐには、tableにtable-layout: fixedを指定するのが定石。

table {
  table-layout: fixed;
}

td {
  width: 200px; /* 効く! */
}

table-layout: fixed;を使えば、テーブルのレイアウトが固定されます。

各列の幅は、最初の行のセルを基準に決まるので、2行目以降のセルにwidthを指定しても意味がありません。

ただし、固定レイアウトにすると、セルのコンテンツがはみ出す可能性もあるので、その点は要注意。

状況に応じて、table-layout: autoとの使い分けが肝心ですね。

○サンプルコード8:スタイルシートの読み込みを確認する

ここまでは、widthが効かない原因をCSSのプロパティやルールに求めてきましたが、そもそもスタイルシートが正しく読み込めていなければ、どんなCSSを書いても意味がありません。

例えば、こんなHTMLとCSSがあったとします。

<head>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="box">
    コンテンツ
  </div>
</body>
/* style.css */
.box {
  width: 300px;
  height: 200px;
  background-color: #f0f0f0;
}

一見問題なさそうですが、もしstyle.cssのパスが間違っていたら、.boxのスタイルは一切適用されません。

この場合、widthを指定しても効かないのは当然の結果なんです。

こんな時は、開発者ツールを使ってCSSが正しく読み込めているか確認するのが一番手っ取り早いです。

ChromeならF12キーを押せば開発者ツールが開くので、そこでNetworkタブを選択し、CSSファイルの Status が 200 OKになっているかどうかをチェックしましょう。

もし404 Not Foundなどのエラーが出ていれば、リンクタグのhref属性を見直す必要があります。

相対パスで指定している場合は、HTMLファイルからの相対位置になっているか、スペルミスがないかなどを確認。絶対パスなら、URLが正しいかどうかを再チェックするのがポイントです。

バグ取りでつい見落としがちですが、スタイルシートの読み込みは、CSSが機能するための大前提。

widthに限らず、スタイルが効かない時は、まずはここを疑ってみると良いかもしれませんね。

○サンプルコード9:ベンダープレフィックスを付ける

次に、ベンダープレフィックス絡みのトラブルを見てみましょう。

<div class="box">
  コンテンツ
</div>
.box {
  display: flex;
  width: 100%; /* 効かない! */
}

このコードでは、flexboxを使ってレイアウトを組んでいますが、widthの指定が効いていません。

もしかすると、古いブラウザでflexboxに対応していないのかもしれません。

こういう時は、ベンダープレフィックスを付けてみるのが一つの解決策です。

.box {
  display: -webkit-flex;
  display: flex;
  width: 100%; /* 効く! */
}

こうすることで、WebKitベースのブラウザでもflexboxが使えるようになります。

すると、widthも期待通りに効くようになるはず。

もちろん、ベンダープレフィックスはあくまで暫定的な措置。

将来的には、プレフィックス無しのプロパティに統一されるのが理想です。

でも、過渡期にあるいま、幅広いブラウザ対応を考えるなら、プレフィックスは欠かせない存在だと言えるでしょう。

Can I useなどを活用して、必要最小限のプレフィックスに絞り込むのがおすすめ。

あまりに多くのプレフィックスを付けすぎると、コードの可読性が下がるので、バランス感覚が大切ですよ。

○サンプルコード10:リセットCSSの影響を排除する

最後は、リセットCSSが招く落とし穴についてお話ししますね。

<div class="container">
  <div class="inner">
    コンテンツ
  </div>
</div>
* {
  margin: 0;
  padding: 0;
}

.container {
  width: 800px;
}

.inner {
  width: 100%; /* はみ出る! */
  padding: 20px;
}

ここでは、ユニバーサルセレクタを使ってmarginとpaddingを0にリセットしています。

一見便利そうですが、これが逆にwidthの計算を狂わせる原因になることも。

box-sizingの初期値はcontent-boxなので、paddingを加えるとコンテンツ領域の幅が800pxを超えてしまうんですよね。

その結果、.innerがはみ出して表示される、と。

これを防ぐには、リセットCSSを見直すのが一番の近道。

ユニバーサルセレクタは使わずに、本当に必要な要素だけをリセットするのがおすすめです。

あるいは、リセットCSSを使う代わりにノーマライズCSSを採用するのも一案。

ノーマライズCSSなら、ブラウザ間の差異を吸収しつつ、有用なデフォルトは残してくれるので、widthへの影響も最小限に抑えられるはずです。

リセットCSSは便利な反面、罠も多いスタイルシート。

widthに限らず、レイアウトがおかしくなった時は、一度疑ってみる価値は十分にあると思います。

もし過剰なリセットが原因なら、思い切ってカスタマイズするのもありですよ。

●widthに関するよくある質問

これまでwidthが効かない原因と対処法をサンプルコードと共に詳しく見てきましたが、まだまだ疑問は尽きないですよね。

ここからは、そんなwidthにまつわるよくある質問を取り上げてみたいと思います。

○width: autoとwidth: 100%の違いは?

まず最初の質問は、width: autoとwidth: 100%の違いについて。

この2つは一見同じように見えて、実は大きく異なる動作をするんです。

width: autoは、要素の幅をコンテンツに合わせて自動的に調整します。

つまり、中身の量に応じて伸び縮みするということ。

一方、width: 100%は親要素の幅いっぱいに広がるよう指定するルール。親の幅が変われば、それに合わせて子要素の幅も変化します。

使い分けのポイントは、「コンテンツ主導か、レイアウト主導か」という点。コンテンツを優先したいなら、autoを選ぶのがベター。逆

にレイアウトを優先したいなら、100%を使うのが賢明でしょう。

ただし、autoを使う時は注意が必要。

段組レイアウトなどで、隣接する要素の幅がautoだと、それぞれのコンテンツ量に応じて勝手に幅が決まってしまうので、デザインが崩れる可能性大。

そんな時は、親要素でflexboxなどを使って、子要素の幅を制御するのがおすすめですよ。

○widthとmax-width、min-widthの関係は?

width、max-width、min-widthは三つ巴の関係にあるプロパティ。

それぞれ役割は違いますが、うまく併用することで、より柔軟なレイアウトが実現できるんです。

まず、widthはいわば「基準値」。

これを中心に、max-widthは上限値、min-widthは下限値を設定するイメージですね。

つまり、widthで指定した幅を基本としつつ、コンテンツの増減に合わせて伸縮できる範囲を制限するといった感じです。

例えば、こんな風に書くことができます。

.box {
  width: 800px;
  max-width: 100%;
  min-width: 500px;
}

この場合、.boxの幅は基本的に800pxですが、ビューポートが800pxより狭くなると、それに合わせて100%まで縮小。

逆に、コンテンツが増えて500pxを超えるようだと、500pxまで広がることができる、というわけです。

○width: 100%を指定するとはみ出るのはなぜ?

width: 100%;を指定すると、要素が親要素の幅いっぱいに広がるのは前述の通り。

でも、時にはその動作が仇となって、コンテンツがはみ出してしまうこともあるんです。

例えば、こんなHTMLとCSSがあったとします。

<div class="container">
  <div class="inner">
    コンテンツ
  </div>
</div>
.container {
  width: 800px;
}

.inner {
  width: 100%;
  padding: 20px;
}

ここで、.innerにwidth: 100%;を指定しているので、.containerの幅である800pxいっぱいに広がるはず。

しかし、同時にpaddingも20px設定されているので、実際のコンテンツ領域の幅は840pxになってしまいます。

つまり、はみ出る原因になるということ。

これは、box-sizingの初期値がcontent-boxであることに起因する問題。

content-boxでは、widthはコンテンツ領域の幅のみを表し、paddingやborderは別枠で計算されるんですよね。

だから、100% + paddingという計算式が成り立ってしまうわけです。

この問題を解決するには、box-sizingをborder-boxに変更するのが一番手っ取り早い。

.inner {
  box-sizing: border-box;
  width: 100%;
  padding: 20px;
}

こうすれば、paddingやborderもwidthに含まれるようになるので、トータルの幅が親要素を超えることはありません。

レスポンシブデザインでは特に重宝するテクニックですね。

ただ、これはあくまで対症療法。

根本的な解決は、「widthとpaddingのバランスを考えること」だと思います。

例えば、最初から.containerのwidthを840pxにしておくとか、.innerのwidthを calc(100% – 40px) にするとか。

状況に応じて柔軟に対応できるようになると、CSSの理解が一段深まるはずですよ。

○tableのwidthが効かないのはなぜ?

次は、tableのwidthが効かない理由について考えてみましょう。

tableは、他の要素とは少し毛色の違うタグ。

セルの幅は、基本的にコンテンツに応じて自動的に決まるので、width属性やCSSでwidthを指定しても、それは「最小幅」としてしか扱われないんです。

例えば、こんなテーブルがあったとします。

<table>
  <tr>
    <td>セル1セル1セル1</td>
    <td>セル2</td>
  </tr>
</table>
td {
  width: 100px;
}

ここでは、tdにwidth: 100px;を指定していますが、1つ目のセルのコンテンツが長いので、実際の幅はそれに合わせて広がってしまいます。

2つ目のセルも、100pxよりコンテンツが短いので、余白ができてしまう。

つまり、width指定が効いていないということですね。

これを解決するには、table要素にtable-layout: fixedを指定するのが定石。

table {
  table-layout: fixed;
}

td {
  width: 100px;
}

こうすることで、テーブルのレイアウトが「固定」されます。

具体的には、各列の幅が最初の行のセルを基準に決定され、2行目以降のセルは無視されるようになるんです。

その結果、tdのwidth指定がしっかりと効くようになる、と。

ただし、この方法にも落とし穴があります。

固定レイアウトだと、セルのコンテンツが幅からはみ出してしまう可能性があるんですよね。

そんな時は、word-break: break-allなどを使って、強制的に改行させるのも手。

状況に応じた使い分けが肝心です。

○flexboxでwidthが効かないのはなぜ?

最後は、flexboxとwidthの関係について。

flexboxは、モダンなレイアウトには欠かせない機能ですが、通常のHTMLタグとは勝手が違うので、width指定が思うように効かないことがあります。

典型的なのが、こんなパターン。

<div class="flexbox">
  <div class="item">アイテム1</div>
  <div class="item">アイテム2</div>
  <div class="item">アイテム3</div>
</div>
.flexbox {
  display: flex;
}

.item {
  width: 200px;
}

ここでは、flexコンテナの子要素である.itemに200pxのwidthを指定していますが、実際には親の幅に合わせて伸縮します。

これは、flexboxのデフォルトの動作。

アイテムの幅は、flex-basisプロパティで決まるんですよね。

これを回避するには、flex-shrinkを0にするのが手っ取り早い解決策。

.item {
  flex-shrink: 0;
  width: 200px;
}

こうすれば、アイテムは絶対に縮小されなくなるので、常にwidth: 200px;が適用されるようになります。

ただし、この方法だとアイテムの合計幅が親を超えた時に、はみ出してしまう恐れがあります。

理想は、各アイテムのwidthを%指定して、flex-growとflex-basisをうまく調整することです。

まとめ

CSSのwidthプロパティ、一見シンプルに見えて奥が深いですね。

親子関係、優先順位、box-sizing、flexboxなど、関連する概念は幅広く、どれも押さえておくべきポイントばかり。

でも、だからこそ面白いのがCSSの世界。

様々なパズルのピースを組み合わせて、理想のレイアウトを実現していく。

そんな創造的な作業は、エンジニアならではの醍醐味だと思います。

width効かない問題に悩んだら、今回紹介した20のチェック項目を思い出してみてください。

どこかに必ず答えへの鍵が隠れているはず。そして、その鍵を見つけた時の喜びを糧に、さらに上を目指す。

それがプロのWebデザイナーへの道のりだと信じています。

あなたなりのCSS設計を探究する旅を、ぜひ楽しんでくださいね。

きっとその先には、もっとクリエイティブで自由なWebデザインが待っているはずです。