CSSで枠からはみ出た部分の文字色を変えるデザイン（伝われ...!!）を作る

こんにちは、うっちーです。
この記事は[Life is Tech! Tokai Mentors Advent Calendar 2018](https://qiita.com/advent-calendar/2018/lit-tokai-mentors)の12日目です。
今回はCSSの記事になります。

# 作るもの
今回は雑誌とかでたまに見かける、枠からはみ出た部分の文字色が変わっているデザインを作っていきます。
言葉では伝わらないと思うのですが下のようなデザインです。
![split_text.png](https://qiita-image-store.s3.amazonaws.com/0/321102/29fb5179-36e3-b629-e23d-20ff2c6b09f8.png)

# 構想
上の画像はIllustratorで作ったのですが、まずはその手順を思い出してみます。
1. 背景色を決める
2. 下半分にボックスを置く
3. 文字を配置し、複製する
4. 文字の一つを下半分のボックスで切り抜く
これを単純にHTMLとCSSで再現すれば基本的にはできるはずです。

# 作ってみる
## HTML + CSS (一番単純なパターン)
とりあえず何も考えずに作ってみます。

```html:HTML
<div id="main-box">
  <p>Think Better</p>
  <div id="split-box">
    <p>Think Better</p>
  </div>
</div>
```

```css:CSS
#main-box {
  width: 500px;
  height: 500px;
  background: #E1C0B6;
  position: relative;
  margin: 0;
  padding: 0;
}
#split-box {
  width: 100%;
  height: 250px;
  background: #EBEBC1;
  position: absolute;
  top: 50%;
  overflow: hidden;
}
#main-box p {
  position: absolute;
  width: 100%;
  text-align: center;
  font-size: 40px;
  font-weight: 600;
  line-height: 40px;
  margin: 0;
  
}
#main-box > p {
  bottom: 230px;
  color: #EBEBC1;
}
#split-box > p {
  top: -20px;
  color: #E1C0B6;
}
```

これでできました。
https://codepen.io/RiField/pen/oJXxEm

### 解説
なんのことはありません。
ただ単に2つの文字列がボックスからはみ出す量が同じになるように`line-height`の半分だけ中心からずらした位置にそれぞれ配置しました。そのうち下側の文字列の飛び出した部分を`#split-box`の`overflow: hidden`で隠しただけです。

## HTML + CSS (ちょっと改善)
1つ目の例は同じ文字列が2度出てくるというとてもきれいとは言い難いものでした。
次はこれを少し改善してみます。

```html:HTML
<div id="main-box">
  <p>Think Better</p>
  <div id="split-box" data-text="Think Better">
  </div>
</div>
```

```css:CSS
#main-box {
  width: 500px;
  height: 500px;
  background: #E1C0B6;
  position: relative;
  margin: 0;
  padding: 0;
}
#split-box {
  width: 100%;
  height: 250px;
  background: #EBEBC1;
  position: absolute;
  top: 50%;
  overflow: hidden;
}
#main-box p,
#split-box::after {
  position: absolute;
  width: 100%;
  text-align: center;
  font-size: 40px;
  font-weight: 600;
  line-height: 40px;
  margin: 0;
}
#main-box > p {
  bottom: 230px;
  color: #EBEBC1;
}
#split-box::after {
  content: attr(data-text);
  position: absolute;
  width: 100%;
  text-align: center;
  left: 0;
  top: -20px;
  color: #E1C0B6;
}
```
これでも同様の結果が得られます。
https://codepen.io/RiField/pen/KbpzLX

## 解説
今回は`data-*`属性と`::after`要素を利用してHTMLから連続していたpタグを取り除いてみました。
`data-*`属性はCSSから格納した情報を取得することが可能なのでここにテキストを入れて、`::after`要素で取得、表示を行っています。
※`::before`要素も利用すると完全にpタグをなくすことができるのですが、アクセシビリティの観点から言うとどちらかは残すべき、ということで一つは残しています。

>Do not store content that should be visible and accessible in data attributes, because assistive technology may not access them. In addition, search crawlers may not index data attributes' values.
[Using data attributes | MDN](https://developer.mozilla.org/ja/docs/Learn/HTML/Howto/Use_data_attributes)

[::after (:after) | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/::after)


## HTML + CSS + JS
上の例ではデザインが機能するためには2箇所の文字列を同じにしておく必要があります。
メンテナンスの面を考えるとこれはあまり良くない（かもしれま）せん。
どうせならjavascriptを使ってテキストを編集するだけでデザインが機能するようにしておきましょう。

```html:HTML
<div id="main-box">
  <p id="text">Think Better</p>
  <div id="split-box">
  </div>
</div>
```

```css:CSS
#main-box {
  width: 500px;
  height: 500px;
  background: #E1C0B6;
  position: relative;
  margin: 0;
  padding: 0;
}
#split-box {
  width: 100%;
  height: 250px;
  background: #EBEBC1;
  position: absolute;
  top: 50%;
  overflow: hidden;
}
#main-box p,
#split-box::after {
  position: absolute;
  width: 100%;
  text-align: center;
  font-size: 40px;
  font-weight: 600;
  line-height: 40px;
  margin: 0;
  
}
#main-box > p {
  bottom: 230px;
  color: #EBEBC1;
}
#split-box::after {
  content: attr(data-text);
  position: absolute;
  width: 100%;
  text-align: center;
  left: 0;
  top: -20px;
  color: #E1C0B6;
}
```

```javascript:JavaScript
window.addEventListener('DOMContentLoaded', function() {
  text = document.getElementById("text").innerHTML; 
  document.getElementById("split-box").setAttribute("data-text",text);
})
```
これでいいでしょうか。
https://codepen.io/RiField/pen/ebNdyJ
### 解説
ｊｓを追加した以外は基本的に変わっていません。
jsも`innerHTML`でテキストの内容を取得して、`setAttribute`で`#split-box`の`data-text`属性にその内容を渡しているだけです。

# まとめ
CSSが少しトリッキーかもしれませんが、わかってしまえばやっていることは単純です。
今回のように簡単なデザインであればIllustratorで作る際のレイヤーなどの考え方を利用してWebもデザインしていくことができるはずです。

ぜひ楽しいWebライフを！