いろいろなCSSの記述方法(メモ)

HTML5+CSS3で新サイトを構築していたら、CSSの特にセレクタ周りでいろいろとできるな~と思ったので忘れないうちにメモしておきます。ちなみにCSS3からのセレクタもありますが、CSS2.1でもセレクタはたくさんありました。それらも含めて使ったものの紹介なので、CSS3に特化したものではないことにご注意ください。

まずはよくある「最初だけ」とか「最後だけ」とか「偶数・奇数」などなど。

htmlコード

<section id="contents">

  <h1>title</h1>

  <article>
    <h2>sub_title1</h2>
    <p>contents1</p>
  </article>

  <article>
    <h2>sub_title2</h2>
    <p>contents2</p>
  </article>

  <article>
    <h2>sub_title3</h2>
    <p>contents3</p>
  </article>

  <article>
    <h2>sub_title4</h2>
    <p>contents4</p>
  </article>

</section>

例えばこのようなソースがあったとします。この時以下のことをやるには…

1.最初のコンテンツだけ枠をつけたい
CSSコード

#contents article:first-child {
  border:1px solid;
}

2.最後のコンテンツだけ枠をつけたい
CSSコード

#contents article:last-child {
  border:1px solid;
}

3.偶数のコンテンツだけ枠をつけたい
CSSコード

#contents article:nth-child(even) {
  border:1px solid;
}

4.奇数のコンテンツだけ枠をつけたい
CSSコード

#contents article:nth-child(odd) {
  border:1px solid;
}

まあ、このあたりはgoogle先生でCSSセレクタで探すと普通に書いてありますね。
さらに…

5.最初のコンテンツ以外に枠をつけたい
CSSコード

#contents article:not(:first-child) {
  border:1px solid;
}

上記5の書き方で他に、
・特定のclassが描かれているコンテンツを省く
CSSコード

#contents article:not([class="hoge"]) {
  border:1px solid;
}

などもできますね!

これらは組み合わせることもできるので、例えば
CSSコード

section:not(:last-child) article:ntn-child(odd) {
  border:1px solid;
}

とかすると、最後のセクション以外の奇数のアーティクルに枠をつけるなんてこともできますね。

もっと変態な書きかたをすれば…

#contents article:not(:first-child):not(:last-child) {
  border:1px solid;
}

なんて書けば最初と最後のアーティクル以外に枠をつけます。

いやぁ、深いですねぇ。

レスポンシブWebデザインの時に考えるhtaccess

最近はレスポンシブWebデザインでホームページを作ることも増えてきましたよね。

ただ、気をつけなくてはいけないのが、スマートフォンなどの携帯ブラウザで見たときも同じサイズの画像が表示されるってことです。(基本的にはですけどね)

CSSの書き方にもよるのでしょうけど、@media screen and (max-width: 569px)なんて書き方で分岐していても、CSSで読まれていないはずの場所の画像が実は読まれているなんてことはよく耳にします。FireMobileSimulatorなどを導入してFirebugなどで調べれば実際に読み込まれているか調査できますのでご自身のサイトで確認してみるといいですよ。

で、media screenなどの分岐ではなく、画像はそのまま表示しちゃいましょうとなると、やはり気になるのは画像サイズですね。

PCブラウザ用に作られた画像は、例えば文字の乗って入るバナーのような画像とか、ファイルサイズ的にはそんなに大きくなくても、スマートフォンの小さな画面に縮小されてしまうと文字が読めなくなるなどの弊害も考えられます。

今回、管理サイトのリニューアルに際し、サイトのWidthが大きくなることになりました。そしていくつかのランディングページ的な役割のファーストビュー部分をインパクトを持たせるためにサイドバーなしの大きな画像で表現することになってしまったため、その大きな画像をスマートフォンに読ませないために色々工夫することになりました。

そこで思いついたのがスマートフォン用の画像を別に用意してhtaccessで分岐させてしまおうという方法です。

ただし、すべての画像をスマートフォン用に用意するのは嫌なので、スマートフォン用の画像が用意されている場合はそちらを読み込み、それ以外はPC用の画像をそのまま使用するという方法で行うことにしました。

しかし、タブレット(iPadやAndroidタブレット)ではPC用の表示を行いたいためスマフォ用画像は使わない(タブレットを省く)設定にしなくてはいけません。

で、行き着いた先のhtaccessがこちらです。

# スマートフォンでアクセスがあった場合に画像フォルダを変更
RewriteEngine on
RewriteBase /img/

RewriteCond %{REQUEST_URI} !mobile/
RewriteCond %{HTTP_USER_AGENT} (iPhone|iPod|Android.*Mobile|BlackBerry|Windows\ Phone|Windows\ CE) [NC]
RewriteCond %{REQUEST_URI} ^/img/(.*)$
RewriteCond %{DOCUMENT_ROOT}/img/mobile/$1 -f
RewriteRule (.*) /img/mobile/$1 [R,L]

ルートにimgのフォルダがあります。その中に普通にページごとにフォルダ分けされており、/img/hoge/fuga.jpgなどのように置かれています。

スマートフォン用の画像はimgの下にmobileフォルダを作り、PC用画像のフォルダと同じ構成で/img/mobile/hoge/fuga.jpgなどのように置いています。

まず{REQUEST_URI}でmobileフォルダの場合はリライトを無効にします。

次に{HTTP_USER_AGENT}でスマートフォンを抜き出しますが、Androidには携帯とタブレットの両方があります。iPadはUserAgentがはっきり分かれていますが、Androidはどちらもほぼ同じです。しかし、Android携帯の場合UserAgentにmobileという記述が入ってくるらしいので、これが入っていないものはタブレット(もしくはAndroidOS搭載のPC?)とみなしてリライトしません。(Windows系の記述はどっかからの丸コピで実際に試していませんのでご注意)

そして次の行でimg以下のURLを取得し、RewriteCond %{DOCUMENT_ROOT}/img/mobile/$1 -fでmobileフォルダ配下に画像が存在しているかどうかを-fのフラグでチェックしています。この「リライト先に画像があるのかないのか?」の判定をhtaccess上で行うのがちょっと苦労しました。Neo Inspirationさんの.htaccess で RewriteCond の後方参照がとても参考になりましたのでご紹介しておきます。

iPhone4S、iPad、Android携帯での実機検証もしていますが、何か不具合や問題点の指摘などがありましたら教えてください。自力だとこれが限界です(汗)ソーシャルの力を信じましょうw

IE7でbackground-color:inheritの問題

ん~、またバグなのかどうなのか、いまいち分からない問題を発見ヽ(´ー`)ノ

文字の色を<em class="font_red">赤</em>にする。

このようなコードの場合で、cssを以下のように

.font_red { /* 赤色 */
	color: red;
	background-color:inherit;
}

記述した場合文字が赤色にならない。
これを以下のように

.font_red { /* 赤色 */
	background-color:inherit;
	color: red;
}

入れ替えるだけで反映されるようになる。
background-color:inherit指定がだめなのか、順番が問題なのかは不明。

ちなみに、以下のように

.font_red { /* 赤色 */
	color: red;
	background-color:blue;
}

などと色を指定した場合はどちらも反映されます。

CSS3でdisplay:boxを使う

えっと、HTML5+CSS3で新規ページを作り始めたわけですが、いろいろはまった上に後で忘れそうなので【メモ】残します。

まず、(X)HTML5+CSS3での3カラムデザインを行うためにdisplay:box;を使おうとしているわけですが、以下コード。

<div id="container">
  <section data-role="content" id="contents">
    <h2>main_content</h2>
    <article>
      <p>main</p>
    </article>
  </section>
  <nav id="sidebar_left">
    <h3>sidebar_left</h3>
    <ul>
      <li>menu_1</li>
      <li>menu_2</li>
      <li>menu_3</li>
    </ul>
  </nav>
  <nav id="sidebar_right">
    <h3>sidebar_right</h3>
    <ul>
      <li>menu_1</li>
      <li>menu_2</li>
      <li>menu_3</li>
    </ul>
  </nav>
</div><!-- END div#container -->

このコードでCSSを記述して3カラムを作ります。次にCSSコード。

#container {
  width:100%;
  display:box;
  display:-moz-box;
  display:-webkit-box;
  display:-ms-box;
}

#sidebar_left {
  width:18%;
  box-ordinal-group:1;
  -moz-box-ordinal-group:1;
  -webkit-box-ordinal-group:1;
  -ms-box-ordinal-group:1;
  background-color:#CF6;
}

#contents {
  width:64%;
  box-ordinal-group:2;
  -moz-box-ordinal-group:2;
  -webkit-box-ordinal-group:2;
  -ms-box-ordinal-group:2;
  -webkit-box-sizing:border-box;
  background-color:#FFF;
  padding:5px;
}

#sidebar_right {
  width:18%;
  box-ordinal-group:3;
  -moz-box-ordinal-group:3;
  -webkit-box-ordinal-group:3;
  -ms-box-ordinal-group:3;
  background-color:#9999FF;
}

これはCSS3のdisplay:boxを使って、ソース上ではコンテンツが先でサイドバーがあとに記述されているような状況でも、box-ordinal-groupで順番を変更して表示してしまいましょうという方法です。

Chromeでは普通に表示できるんですけどね。Firefoxでdisplay:boxを使用し、かつ子要素の幅を%(パーセント)で指定すると幅がなくなっちゃいます。
なぜ%(パーセント)指定したいかというと、@media screen and (max-width: 1000px)  なんてやってリキッドデザインを目指すとどうしても必要になっちゃうんですね。

そこで、Firefox用にCSSを少し足します。

#sidebar_left {
  -moz-box-flex:1;
}

#contents {
  -moz-box-flex:1;
  max-width:640px;
}

#sidebar_right {
  -moz-box-flex:1;
}

-moz-box-flexで幅を均等にした上でmax-width:640pxで想定している最大の幅を指定しました。(当方の場合、最大幅1000pxでサイドバーの最大幅を180pxとしているため)

最初はFirefoxでcontentsに入力していたダミーの文字が折り返されずに表示されてしまったためにデザインが崩れてしまっていました。上記-moz-box-flexで相対幅をしていするとなぜか直ったのでこれを利用しています。%(パーセント)指定が効かないのはなぜなのかわかりません。。。

IE7のcssでの画像置換がおかしい

まあ、いまさらIE7?とか言われそうですが、アクセスログを取得している限りまだまだ捨て切れません。(さすがにIE6は切り捨てましたが・・・)

で、よくあるcssでの画像置換に関してなのですが、IE7で妙な挙動をします。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>inline-block test</title>
<style type="text/css">
	div#design ul {
		display:block;
		width:550px;
	}

	div#design ul.ie7out li {
		display:inline-block;
		width:146px;
		height:80px;
		/display:inline;
		/zoom:1;
		text-indent:-9999px;
	}

	div#design ul.ie7ok li {
		display:inline-block;
		width:146px;
		height:80px;
		/display:inline;
		/zoom:1;
	}

	div#design ul.ie7ok li span {
		display:none;
	}

	div#design ul li.a {
		background:url(circle_banner_01.gif) no-repeat;
	}

	div#design ul li.b {
		background:url(circle_banner_02.gif) no-repeat;
	}

	div#design ul li.c {
		background:url(circle_banner_03.gif) no-repeat;
	}
</style>
</head>
<body>
<div id="design">
<p>IE7で消える?</p>
<ul class="ie7out">
	<li class="a">A</li>
	<li class="b">B</li>
	<li class="c">C</li>
</ul>

<p>IE7でも消えない?</p>
<ul class="ie7ok">
	<li class="a"><span>A</span></li>
	<li class="b"><span>B</span></li>
	<li class="c"><span>C</span></li>
</ul>

</div><!-- END div#design -->
</body>
</html>

こんなコードで試してみました。

display:inline-block;を利用して横に画像を並べるコードですが、IE7では対応していないため良くあるハックを使用しています。

/display:inline;
/zoom:1;

この状態でtext-indent:-9999px;として文字を飛ばすとIE7の場合だけ画像ごと飛んでいってしまいます。display:inline-block;を利用していますので、display:none;と言うわけにもいきません。

そこで面倒ですがliタグの中にさらにspanタグを入れて、そのspanタグを文字ごと飛ばす方法で対応してみました。環境のある方は上記コードでIE7とFirefoxなどのメジャーブラウザで確認してみてください。メジャーブラウザでは両方とも画像が表示されます。