3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

レスポンシブや反転、余白の変更、垂直方向の変更ができるMediaオブジェクト

Last updated at Posted at 2015-12-14

OOCSSでよく取り上げられるMediaオブジェクトに4つのModifierを指定できるように作ってみました。以下の4つのパターンを組み合わせて指定できます。もちろんネストにも対応しています。

  • paddingプロパティで3段階の余白指定
  • vertical-alignプロパティで3段階の垂直位置指定
  • directionプロパティで要素の反転
  • display: block;でブレイクポイント以下で横並びから縦並びに変更

CodePenにデモを用意しています。

See the Pen Media object by ManabuYasuda (@gaku) on CodePen.

マークアップ

マークアップは以下のように記述します。BEMっぽくはなっていますが、マークアップをシンプルにするためにElementBlock__Element--Modifierにはしていません。[]はModifierであることを示しています。

<div class="c-media [c-media--small c-media--middle c-media--rev c-media--stack-md]">
  <div class="c-media__item">
    <img>
  </div>
  <div class="c-media__item">
    <p></p>
  </div>
</div>

ネストする場合は以下のように.c-media__itemの中に.c-mediaを入れ子にします。

<div class="c-media">
  <div class="c-media__item">
    <img src="">
  </div>
  <div class="c-media__item">
    <p></p>
    <!-- ここからがネスト -->
    <div class="c-media">
      <div class="c-media__item">
        <img src="">
      </div>
      <div class="c-media__item">
        <p></p>
      </div>
    </div>
    <!-- ネストの終了 -->
  </div>
</div>

Sassコード

4つのModifierを指定するのでソースコードがやや複雑になっています。Sassが分かる人はCSSよりも把握しやすいと思います。

$media-gutter: 1em !default;
$media-gutter-small: ($my-media-gutter / 2) !default;
$media-gutter-large: ($my-media-gutter * 2) !default;

.c-media {
    display: table;
    width: 100%;
    margin: 0;
    padding: 0;
}

.c-media__item {
    display: table-cell;
    margin: 0;
    padding: 0;
    vertical-align: top;
    &:not(:first-child) {
        padding-left: $my-media-gutter;
    }
    & > :first-child {
        margin-top: 0;
    }
    & > :last-child {
        margin-bottom: 0;
    }
}

.c-media__item > img {
    display: block;
}

.c-media--middle {
    > .c-media__item {
        vertical-align: middle;
    }
}

.c-media--bottom {
    > .c-media__item {
        vertical-align: bottom;
    }
}

.c-media--rev {
    text-align: left;
    direction: rtl;
    > .c-media__item {
        text-align: left;
        direction: ltr;
    }
    > .c-media__item:not(:first-child) {
        padding-right: $my-media-gutter;
        padding-left: 0;
    }
}

.c-media--small {
    > .c-media__item:not(:first-child) {
        padding-left: $my-media-gutter-small;
    }
    &.c-media--rev > .c-media__item:not(:first-child) {
        padding-right: $my-media-gutter-small;
        padding-left: 0;
    }
}

.c-media--large {
    > .c-media__item:not(:first-child) {
        padding-left: $my-media-gutter-large;
    }
    &.c-media--rev > .c-media__item:not(:first-child) {
        padding-right: $my-media-gutter-large;
        padding-left: 0;
    }
}

@media screen and (max-width: 399px) {
    .c-media--stack-sm {
        > .c-media__item {
            display: block;
        }
        > .c-media__item:not(:first-child) {
            padding: $my-media-gutter 0 0;
        }
        > .c-media__item > img {
            margin: auto;
        }
        &.c-media--small > .c-media__item:not(:first-child) {
            padding: $my-media-gutter-small 0 0;
        }
        &.c-media--large > .c-media__item:not(:first-child) {
            padding: $my-media-gutter-large 0 0;
        }
    }
}

@media screen and (max-width: 767px) {
    .c-media--stack-md {
        > .c-media__item {
            display: block;
        }
        > .c-media__item:not(:first-child) {
            padding: $my-media-gutter 0 0;
        }
        > .c-media__item > img {
            margin: auto;
        }
        &.c-media--small > .c-media__item:not(:first-child) {
            padding: $my-media-gutter-small 0 0;
        }
        &.c-media--large > .c-media__item:not(:first-child) {
            padding: $my-media-gutter-large 0 0;
        }
    }
}

CSSコード

Sassコードをコンパイルすると以下のようになります。

.c-media {
    display: table;
    width: 100%;
    margin: 0;
    padding: 0;
}

.c-media__item {
    display: table-cell;
    margin: 0;
    padding: 0;
    vertical-align: top;
}
.c-media__item:not(:first-child) {
    padding-left: 1em;
}
.c-media__item > :first-child {
    margin-top: 0;
}
.c-media__item > :last-child {
    margin-bottom: 0;
}

.c-media__item > img {
    display: block;
}

.c-media--middle > .c-media__item {
    vertical-align: middle;
}

.c-media--bottom > .c-media__item {
    vertical-align: bottom;
}

.c-media--rev {
    text-align: left;
    direction: rtl;
}
.c-media--rev > .c-media__item {
    text-align: left;
    direction: ltr;
}
.c-media--rev > .c-media__item:not(:first-child) {
    padding-right: 1em;
    padding-left: 0;
}

.c-media--small > .c-media__item:not(:first-child) {
    padding-left: 0.5em;
}

.c-media--small.c-media--rev > .c-media__item:not(:first-child) {
    padding-right: 0.5em;
    padding-left: 0;
}

.c-media--large > .c-media__item:not(:first-child) {
    padding-left: 2em;
}

.c-media--large.c-media--rev > .c-media__item:not(:first-child) {
    padding-right: 2em;
    padding-left: 0;
}

@media screen and (max-width: 399px) {
    .c-media--stack-sm > .c-media__item {
        display: block;
    }
    .c-media--stack-sm > .c-media__item:not(:first-child) {
        padding: 1em 0 0;
    }
    .c-media--stack-sm > .c-media__item > img {
        margin: auto;
    }
    .c-media--stack-sm.c-media--small > .c-media__item:not(:first-child) {
        padding: 0.5em 0 0;
    }
    .c-media--stack-sm.c-media--large > .c-media__item:not(:first-child) {
        padding: 2em 0 0;
    }
}

@media screen and (max-width: 767px) {
    .c-media--stack-md > .c-media__item {
        display: block;
    }
    .c-media--stack-md > .c-media__item:not(:first-child) {
        padding: 1em 0 0;
    }
    .c-media--stack-md > .c-media__item > img {
        margin: auto;
    }
    .c-media--stack-md.c-media--small > .c-media__item:not(:first-child) {
        padding: 0.5em 0 0;
    }
    .c-media--stack-md.c-media--large > .c-media__item:not(:first-child) {
        padding: 2em 0 0;
    }
}

コードの解説

table-cellを使用するとvertical-alignプロパティが指定できる

Mediaオブジェクトはfloatプロパティを使ったものがよく使われていましたが、それでは垂直方向の変更ができません。vertical-alignプロパティを指定できるのはインラインレベルとテーブルセル要素です。

適用対象 インラインレベルとテーブルセル要素. It also applies to ::first-letter and ::first-line.

vertical-align - CSS | MDN

今回はtopをデフォルトにしています。

.c-media {
    display: table;
    width: 100%;
    margin: 0;
    padding: 0;
}

.c-media__item {
    display: table-cell;
    margin: 0;
    padding: 0;
    vertical-align: top;
}

.c-media--middle > .c-media__item {
    vertical-align: middle;
}

.c-media--bottom > .c-media__item {
    vertical-align: bottom;
}

要素を反転させるdirectionプロパティ

floatプロパティを使用しないと要素の反転ができないかというと、そうではありません。directionプロパティを使用すればテーブルでも反転することができます。

direction - CSS | MDN

directionプロパティはヘブライ語やアラビア語などの右から左へ読む言語で使用されるものです。親要素にdirection: rtl;を指定することで反転、子要素にdirection: ltr;を指定することで元の状態に戻します。

.c-media--rev {
    text-align: left;
    direction: rtl;
}
.c-media--rev > .c-media__item {
    text-align: left;
    direction: ltr;
}

これはinline-blockにも使用できるので覚えておくとレイアウトの幅が広がります。

:not(:first-child)で余白指定をシンプルにする

余白の指定には否定擬似クラスの:not()を使用しています。Mediaオブジェクトは__image__bodyのようなクラスを指定することが多いですが、否定擬似クラスを使用すると、同じクラスでマークアップすることができます。

.c-media__item:not(:first-child) {
    padding-left: 1em;
}

.c-media--small > .c-media__item:not(:first-child) {
    padding-left: 0.5em;
}

.c-media--large > .c-media__item:not(:first-child) {
    padding-left: 2em;
}

:not() - CSS | MDN

:not()はIE9から使えます。もしIE8でも使いたい場合は以下のように隣接セレクタを使います(詳細度も同じです)。

.c-media__item + .c-media__item {}

隣接セレクタ - CSS | MDN

あるブレイクポイント以下でblockにする

画像とテキストが横並びになるMediaオブジェクトはスマホなどの横幅が狭いデバイスでは縦に並べたい場合もあると思います。メディアクエリを使用してブレイクポイント以下になったときにdisplay: table-cellblockにすることで縦に配置します。

@media screen and (max-width: 767px) {
    .c-media--stack-md > .c-media__item {
        display: block;
    }
    .c-media--stack-md > .c-media__item:not(:first-child) {
        padding: 1em 0 0;
    }
    .c-media--stack-md > .c-media__item > img {
        margin: auto;
    }
    .c-media--stack-md.c-media--small > .c-media__item:not(:first-child) {
        padding: 0.5em 0 0;
    }
    .c-media--stack-md.c-media--large > .c-media__item:not(:first-child) {
        padding: 2em 0 0;
    }
}

paddingプロパティは縦方向にだけ余白を指定するように変更しています。img要素にmargin: auto;を指定しているのはバランス的にセンタリングした方がいいのではということで指定しています。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?