もうすぐクリスマスなのでinputとlabelの仲を引き裂いてみた

本記事は[LIFULLその2 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/lifull2) 17日目の記事になります。

こんにちは。新卒二年目デザイナーのえびといいます。好きな寿司ネタはえんがわです。
主にLIFULL HOME'S新築一戸建てのデザイン・コーディング業務をしています。

最近formを触る機会がありました。
その中でも特に触っていたのがinput・label要素です。
formの中枢を司るinputを影から一生懸命支えるlabel。さながら仲睦まじい夫婦・カップルのようでした。
**爆発してほしい。**

今回はそんなinputとlabelの関係をお話しつつ**破局に導いてみます。**
# inputとlabel
フォームで散見するcheckboxやradioなどのinput要素。
このまま使うと非常にダサイのですが、label要素を使うことによってCSSで自由にデザインできるようになります。
さながら**「仕事は出来るけれどちょっとイケてないinputくんを服屋に連れていくlabelちゃん**のようです。

具体的には、inputとlabelを兄弟要素として配置し、inputをdisplay: none;で**消します**
そして、inputでidと指定されている値をlabelのforに入れてあげると、label要素をinputの代替として使用することができます。
最初に述べたようにlabel要素はCSSが使えるので、デザイン性の高いフォームの作成が可能になります。

レシピは以下になります。
ホバー時・チェック時で何らかの変化があるとより「チェックしている感」が高まりますね。

```html:label+input.html
<input type="checkbox" id="hoge">
<label for="hoge">ラベルテキスト</label>
```
```css:label+input.css
input[type="checkbox"] {
    display: none;
}
label {
    position: relative; /* 擬似要素用に指定 */
    /* 背景色・ラベルカラー・paddingなどをいい感じに設定 */
}

/* チェックボックスの箱 */
label::before {
    content: "";
    position: absolute; /* 絶対位置で場所を指定 */
    /* width, height, backgroundなどで箱をデザインする */
}

/* チェックマーク */
label::after {
    content: "";
    position: absolute; /* 絶対位置で場所を指定 */
    /* width, height, border, transformなどでチェックマークをデザインする */
    /* 非チェック時の表示なので、opacity: 0;を入れてあげる方がよさそう */
}

/* ホバーした時の挙動 */
label:hover {
}
label:hover::before {
}
label:hover::after {
}

/* チェックした時の挙動 */
input[type="checkbox"]:checked + label {
}
input[type="checkbox"]:checked + label::before {
}
input[type="checkbox"]:checked + label::after {
    /* label::afterでopacity: 0;を指定していたら1にしてあげること */
}
```
**デモ**
https://codepen.io/ebisawa-next/pen/rYKzYY

今回は兄弟要素として書きましたが、input **~** labelにすれば間に別の要素が入っていてもOKです。
**（まるで遠距離恋愛。爆発してほしい。）**

inputはinput、labelはlabelとしてまとめて置いておきたいときはそのように記述しましょう。

# input「ごめん…俺…id持ってないんだ…」
inputにidを付与出来ないこと、もしかしたらあるかもしれません。
そんな場合も、label > inputの親子要素にすれば同じように使えます。
まるで**不甲斐ない息子を優しくサポートするｶｰﾁｬﾝ**のようです。

ただ、そのままlabel > inputの親子要素にすると、input:checkedの時の修飾が出来なくなってしまいますので、
以下のようにinput + spanの形にしてあげる必要があります。

```html:label>input.html
<label>
    <input type="checkbox">
    <span>ラベルテキスト</span>
</label>
```
CSSは上で書いたものを label→spanに置換してあげるだけ。かんたん。

**デモ**
https://codepen.io/ebisawa-next/pen/eeLxey
# inputとlabelを引き裂く
兄弟でも親子でもオールオッケーなinput♡labelですが、
**inputだけでも装飾は可能です。**labelなんていらなかったんだ！

inputの**appearanceとoutlineをnoneにしてあげる**ことで、
デフォルトのinputの設定がリセットされます。

```css:lonelinessInput.css
input[type:checkbox] {
    -webkit-appearance: none; /* webkit系はpfが必要 */
    appearance: none;
    outline: none;
}
```
あとはlabel(::before, ::after)に指定していた要素をinputにいれてあげればOKです。
ただ、このままだとテキストの設定がうまくいかないので、htmlも少し手直しします。

```html:lonelinessInput.html
<ul>
    <li>
        <input type="checkbox">
        <span>ラベルテキスト</span>
    </li>
</ul>
```

cssも以下を追記。

```css:lonelinessInput.css
li {
    width: 100px; /* inputの表示領域を担保 */
    position: relative; /* spanのabsolute指定に使う */
}
input[type="checkbox"] + span {
    position: absolute;
    /* top, leftでテキストの位置を調整 */
}
```

**デモ**
https://codepen.io/ebisawa-next/pen/zpvRwx
## 引き裂いたけれど使い勝手はどうなの？
**微妙。**

- span要素をクリックしてもチェック出来ないのでユーザビリティがよろしくない
- 親要素にwidthの値を決めうちでいれないといけないため、耐久性がダメ
- **そもそもli要素使えるならlabelでいいじゃん**

というわけで、**inputだけで生きていくのは無理**という結論に落ち着きました。
inputくんにはlabelちゃんが必要です。君たちお似合いだよ……

とはいえ、
「チェックボックスやラジオボタンの見た目を変えたい！テキストなんか使わないよ！」
という場合はinputの装飾だけでそれっぽいものが作れます。
DOM要素を極限まで減らしたい場合は使えるかもしれません。
# まとめ
- inputとlabelは時と場合によって兄弟・親子で使い分けをしよう
- inputだけでも修飾はできるが、テキストを添える場合は微妙

今回はinputとlabelの仲を引き裂いてみたものの、
**input♡labelカップルの相性が最高すぎて返り討ちに遭いました。**
皆様はこのようなことがないよう、クリスマス前にダメージを食らうのはやめましょう。