position:absoluteで中央寄せになる原理が分からない!!

最終更新日:2023-08-09

公開日:2023-08-09

CSS

今回のお題は、タイトルの通りです。

上下の中央に寄せたいと思ったときに「上下中央寄せ CSS」などで調べると必ずといっていいほど出会う構文

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

上記のようなCSSを皆さんも一度は目にしたことがあるのではないでしょうか?

最初のうちはコピペでいいかもしれませんが、いつか深く理解しないといけない日が来ます。

では、ここで疑問を解消してしまいましょう!

では、早速ですが説明に入ります。

positionについて

まずはpositionというプロパティについてです。次のようなコードを書いてみましょう。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>positionについて</title>
  <style>
    body {
      padding-top: 100px;
    }

    .box {
      width: 300px;
      height: 300px;
      margin: auto;
      background-color: #b0b0b0;
    }
  </style>
</head>

<body>
  <div class="box">
    <h1 class="title">タイトル</h1>
  </div>
</body>

</html>

すると、下の画像のような表示になるはずです。

この状態だと、まだ「タイトル」という文字列は中央に寄っていませんね。

ここでtitleというクラスに次のCSSを指定したらどうなるでしょうか?

position: absolute;
top: 0;
left: 0;

上のコードは、左上の角に寄せたいという意味になります。
全体のコードは下のような形。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>positionについて</title>
  <style>
    body {
      padding-top: 100px;
    }

    .box {
      width: 300px;
      height: 300px;
      margin: auto;
      background-color: #b0b0b0;
    }

    .title {
      position: absolute;
      top: 0;
      left: 0;
    }
  </style>
</head>

<body>
  <div class="box">
    <h1 class="title">タイトル</h1>
  </div>
</body>

</html>

皆さんはどうなるか予想できますか?結果は下の画像です。

あれ、なぜか親要素のボックスからはみ出して、画面の左上に行ってしまいました。。。

これはなぜかというと、

どこを基準に、position:absolute;で位置を決めてあげるのか指定してないから

です。

この場合、親要素である.boxを基準にしてあげたいので、下記のようにコードを書き換えます。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>positionについて</title>
  <style>
    body {
      padding-top: 100px;
    }

    .box {
      position: relative;
      width: 300px;
      height: 300px;
      margin: auto;
      background-color: #b0b0b0;
    }

    .title {
      position: absolute;
      top: 0;
      left: 0;
    }
  </style>
</head>

<body>
  <div class="box">
    <h1 class="title">タイトル</h1>
  </div>
</body>

</html>

上記のコードの、.boxに付与しているposition:relative;が、この要素を基準に、子要素の位置を指定してくださいね、という意味になります。

画面を見てみると下のような形。

ちゃんと.boxの中におさまりましたね。
上に余白がついてしまっていますが、こちらはブラウザがデフォルトで設定してしまうCSSが適用されているからです。

気になる方はリセットCSSなどをあててみましょう。

今回は簡潔に、.titleにmargin: 0を指定してあげます。

positionだけを指定するとどうなる?

では、本題である中央寄せにしてみたいと思います。コードを下記のような形に書き換えましょう。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>positionについて</title>
  <style>
    body {
      padding-top: 100px;
    }

    .box {
      position: relative;
      width: 300px;
      height: 300px;
      margin: auto;
      background-color: #b0b0b0;
    }

    .title {
      margin: 0;
      position: absolute;
      top: 50%;
      left: 50%;
    }
  </style>
</head>

<body>
  <div class="box">
    <h1 class="title">タイトル</h1>
  </div>
</body>

</html>

先ほどまでと違う点としては、.titleのCSSを

    .title {
      position: absolute;
      top: 50%;
      left: 50%;
    }

としたことです。

この状態で画面を見てみましょう。

50%で指定したはずなのに中央に寄っていませんね、、、

なぜなのでしょうか。

それは、position:absoluteで指定する50%というのは、position: relativeが指定されている要素の上の端から50%だからです。

どういうこと?という声が聞こえてきそうなので図解します。

今回は.boxを基準にしているので、横の辺、縦の辺から50%とは上図のような感じになります。

では、どうやって中央に寄せるのか。

そこで大事になるのが次のコードです。

transform: translate(-50%, -50%);

全体のコードは下のような形。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>positionについて</title>
  <style>
    body {
      padding-top: 100px;
    }

    .box {
      position: relative;
      width: 300px;
      height: 300px;
      margin: auto;
      background-color: #b0b0b0;
    }

    .title {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
  </style>
</head>

<body>
  <div class="box">
    <h1 class="title">タイトル</h1>
  </div>
</body>

</html>

画面を見てみると、、、

中央に寄せることができました!

同じ50%なのに何が違うの?

positionで指定した数値と、transformで指定した数値、どちらも50%ですが、中央に寄りました。

これはなぜなのでしょうか?

下の図を参照ください。

transformにおける50%というのは、ここでいうと文字の横幅、縦幅に対しての50%となります。

そのため、position:aboluteで.boxに対して上下左右50%の位置に移動してあげてから、transformで.titleの位置を-50%してあげると中央に寄るということでした。

余談ですが、上の図でタイトルの文字列を囲んでいる四角が綺麗に文字の中央ではないことにお気づきでしょうか?

これは、文字そのものが持つ縦幅、横幅が関係しています。

なので、上下中央揃えにしても、文字自体が中央に寄っていないように見えてしまうことがありますが、大半の原因はこれです。

調整するかしないかは、クライアント様次第です。

まとめ

いかがでしたでしょうか?

今回は諸学者つまづきポイントでもあるpositionの使い方についてでした。

皆様の、これからの学習の励みになれば幸いです。

\ 初学者向けの指導も行ってます /