【CSS Tips】CSSで要素の位置を変える方法と注意点

## これは何

レスポンシブなWebデザインを作成していると、デバイス幅によっては要素の位置が変わることがあります。
そうしたデザインをCSSで実装するときの方法と注意点をまとめました。

## ①`flex-direction`で要素の並び順を逆向きにする

例えば、以下のようなUIを実装することを想定しています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/57a0f23f-c0bb-a9a2-d575-6a31d4ba077e.png)

- デスクトップの時は、`画像`・`テキスト`の順で横並びになっている
- モバイルの時は`テキスト`・`画像`の順で縦並びになっている

この時、単純にモバイルの時は要素が縦並びになるように`flex-direction: column`を指定するだけでは、画像の位置が上になってしまいます。

こうした時には`flex-direction: column-reverse`を指定すると、縦並びにした上に要素の並び順を逆向きにしてくれます。
横並びのまま順番だけ逆にしたい場合は、`flex-direction: row-reverse`を指定します。

https://developer.mozilla.org/ja/docs/Web/CSS/flex-direction

### サンプルコード

```html
<div>
  <img src="hoge" />
  <p>hoge</p>
</div>
```

```css
div {
  display: flex; /* レイアウトを横並びにする */
}

@media screen and (min-width: 500px) {
  div {
    flex-direction: column-reverse; /* デバイスが500px以下の時は並び順を逆順にする */
  }
}
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="OJayjLW" data-user="kabechiyo" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kabechiyo/pen/OJayjLW">
  Untitled</a> by kabechiyo_shunkaaizawa (<a href="https://codepen.io/kabechiyo">@kabechiyo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## ②orderで順番を並び替える

「`flex-direction`で要素の並び順を逆向きにする」では、すべての要素の並び順が逆になってしまうので、一部だけ順番を変えたい時などには使用できません。

そうした時には、orderを使います。

例えば、以下のようなUIを実装することを想定しています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/afec7e20-35ef-f349-6068-da0d3f96f064.png)

- デスクトップの時は、`画像`・`メイン要素`・`サブ要素`の順で横並びになっている
- モバイルの時は、`画像`・`サブ要素`・`メイン要素`の順で縦並びになっている

こうした時には、FlexboxやGridの子要素に`order`を指定することで、並び順を指定できます。

### サンプルコード

```html
<div>
  <img src="hoge" />
  <div class="content"></div>
  <p>hoge</p>
</div>
```

```css
div {
  display: flex; /* レイアウトを横並びにする */
}

@media screen and (min-width: 500px) {
  div {
    flex-direction: column; /* デバイスが500px以下の時はレイアウトを縦並びにする */
  }
  .content {
    order: 3; /* デバイスが500px以下の時はcontentの位置を3番目にする */
  }
}
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="GRwmaBz" data-user="kabechiyo13" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kabechiyo13/pen/GRwmaBz">
  Untitled</a> by かべちよ (<a href="https://codepen.io/kabechiyo13">@kabechiyo13</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## `grid-area`で位置を変える

①や②のように順番を変えるだけでは実現できなかったり、コードが複雑になってしまう場合には`grid-area`を使用するのがおすすめです。

例えば、以下のようなUIを実装することを想定しています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577501/448b82dc-7c63-ffbd-6e85-4058d7fbe23d.png)

- デスクトップの時は、`画像`・`フッター要素`が縦並びになった列・`メイン要素`・`サブ要素`の順で横並びになっている
- モバイルの時は、`画像`・`メイン要素`・`サブ要素`・`フッター要素`の順で縦並びになっている

grid-areaを使うと各要素に名前をつけることができ、名前を使って要素をどうグリッドレイアウト上に配置するかを指定できます。

https://developer.mozilla.org/ja/docs/Web/CSS/grid-template-areas

### サンプルコード

```html
<div>
  <img src="hoge" />
  <p>hoge</p>
  <div class="content"></div>
  <div class="sub_content"></div>
</div>
```

```css
/* 各要素に名前をつける */
img {
  grid-area: image;
}

p {
  grid-area: text;
}

.content {
  grid-area: content;
}

.sub_content {
  grid-area: sub_content;
}

/* 各要素につけた名前を用いてグリッドレイアウトに並べる */
div {
  grid-template-areas:
    "image content sub_content"
    "text content sub_content";
}

/* デバイスが500px以下の時はcontentの位置を3番目にするレイアウトを変える */
@media screen and (min-width: 500px) {
  div {
    grid-template-areas:
      "image" "content" "sub_content" "text";
  }
}
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="xxQppZP" data-user="kabechiyo13" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kabechiyo13/pen/xxQppZP">
  grid-area</a> by かべちよ (<a href="https://codepen.io/kabechiyo13">@kabechiyo13</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## アクセシビリティ上の注意点

CSSで「要素の**見た目上の位置**」を変えた際は、「DOM構造の順番」は変わりません。
そのため、見た目上の順番とスクリーンリーダーなどで読み上げられる要素の順番が異なってしまいます。

CSSで要素の表示順を変えた際は、アクセええシビリティツリー上でも意味が適切に通じるかをチェックする必要があります。

逆に言えば、DOM構造を変えずに見た目の順番を変えられるので、「見た目を実現するためにDOM構造を変え、情報の流れが変わってしまう」ことを防ぐこともできます！