画像の上の要素を中央に配置する方法(2選)

#画像の上に要素を重ねる
まずは画像の上に要素を重ねる方法を2パターン紹介します

#1つ目

```html
<body>
  <div class="image">
    <div>上の要素</div>
  </div>
</body>
```

```css
.image {
  background-image: url(/images/sample.jpg);
}
```

こちらがdivを入れ子にして親要素(今回はclass="image")に対して
cssでbackground-imageを使うことで背景として指定する方法。

urlの指定方法は何パターンかあるので上手くいかない方は
調べてみてください。
今回の記事の趣旨からは逸れてしまうので
説明は割愛させていただきます。

#2つ目

```html
<body>
  <img src="sample.jpg">
  <div>上の要素</div>
</body>
```

```css
img {
  height: 100%
  width: 100%
}

div {
  position: absolute;
  top: 50%;
  left: 50%;
}
```

こちらが並列の要素(今回はimgとdiv)の上にしたい要素に対して
cssでposition: absolute;の絶対値を使い無理やり上にする方法。
今回のcssの場合、imgが画面いっぱいに広がっているところに対して
上の要素という文字がtopから50%、leftから50%の位置を起点として配置されます。

srcの指定方法は階層で変わるので上手くいかない場合は別途お調べください。
imgのサイズが上手くいかない場合はbodyタグにcssを当てる場合があるので
そちらも別途お調べください。
今回の趣旨から外れてしますので説明は割愛させていただきます。

#本題
ではこの2つのパターンでどうすれば中央に配置することができるのかを
それぞれご紹介させていただきます。

#1つ目の中央に配置
上記で使ったものをそのまま使用していきます。

```html
<body>
  <div class="image">
    <div>上の要素</div>
  </div>
</body>
```

```css
.image {
  background-image: url(/images/sample.jpg);
  display: flex;
  justify-content: center;
  align-items: center;
}
```

こちらが1つ目の中央に配置する方法です。
追記された行を1つずつみていきます。

```css
display: flex;
```
こちらが子要素(今回は上の要素という文字のdiv)に対してどのような働きをさせるか指定するものになります。
flexではなくblockなど他の指定もありますので興味がある方は別途調べてみてください。
今回は横並べになるflexを使用しますが子要素が1つしかないので
あまり影響がないと考えてください。
ではなぜわざわざ指定するのかというとdisplayを指定しないとこれから紹介する
追記が反映されないからです。
ここでは子要素に働きかけるという意味で使っていると思ってください。

```css
justify-content: center;
```
こちらが横幅の指定になります。
親要素(今回だとclass="image")の横幅からどの場所に子要素を配置するかです。
ここでcenterを指定することで横幅の中央に配置することができます。

```css
align-items: center;
```
こちらが縦幅の指定になります。
親要素(今回だとclass="image")の縦幅からどの場所に子要素を配置するかです。
centerを指定することで縦幅の中央に配置するとができます。

この2つを使うと親要素の中心に配置することができます。

#2つ目の中央に配置
上記で使ったものをそのまま使用していきます。

```html
<body>
  <img src="sample.jpg">
  <div>上の要素</div>
</body>
```

```css
img {
  height: 100%
  width: 100%
}

div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
```

こちらが2つ目の中央に配置する方法です。
こちらも追記した部分を紹介していきます。

```css
transform: translate(-50%, -50%);
```
詳しい内容は別途調べていただきたいと思いますが、
今回は要素をずらすというような意味合いで使っています。

まず前提として

```css
position: absolute;
top: 50%;
left: 50%;
```
こちらの記述でposition: absolute;の絶対値を使い
topから50%、leftから50%の位置を起点としてdivが配置されていると思います。
しかしこちらだとあくまで起点(divの左上)が画面の中央であって要素が中央ではないかと思います。
そこでこの要素をずらして中央に配置していくという記述です。

順を追って説明すると

```
transform:
```
要素を変形するという記述です。回転や移動などができます

```
transform: translate
```
こちらが移動させるという記述になります。

```
transform: translate(-50%, -50%);
```
そして最後に移動させる距離の指定です。

```
(-50%, -50%);
```
こちらがその指定した要素(cssを当てている要素)の縦と横の長さをそれぞれを
100%とした時、50%分-(マイナスに移動)するという記述です。

周りくどい説明になりましたが簡単にいうと
要素の50%分上と左に移動します。
起点となっていた部分から要素の半分を移動させることでちょうど中央に配置されるということになります。

色々と数値を変えて試していただけると理解しやすいかと思います。

これで2つ目のパターンも中央に配置することに成功しましたが
この両方にはそれぞれデメリットがあるのでそちらも合わせて紹介していきます。

#それぞれのでデメリット

**1つ目のパターン**
背景に指定するので
インスタンス変数などデータベースから引っ張ってくるパターンが適応できない点です。
中央に配置するというだけで言えばこちらの方が確実だと思いますが
cssで背景に指定できるものに限られてしまいます。

**2つ目のパターン**
position: absolute;を使うので汎用性がないという点です。
相対的な位置で変わるのではなく
絶対的な位置で無理やり上に持ってくるので
要素が場合に応じて増えたり、減ったりしてviewが崩れた場合に
合わせて配置を変えてくれません。

そして今回はtop: 50%;でうまく中央になりましたが
viewの途中で入れたいなどの場合、上手く中央に配置されない場合があるという点です。

個人的にあまり使い勝手がいいとは思いませんが
どうしても画像の上に文字を乗せたい場合などはviewの崩れを確認しながら
実装していただければと思います。