質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

CSSテクニックについてです!

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 746

wonda

score 67

初めて投稿させていただきます。

ネット上で共有されていた下記checkbox用のCSSですが、シンプル、かつ滑らかで
とても気に入っているのですが、これをradioボタンで実装出来ないかと思考錯誤していたのですが・・
どなたかお力を貸して頂けないでしょうか。
すみませんが、宜しくお願いします。

※追記

自身で試したコードを載せてみては?と修正依頼を頂きました。
失礼致しました。
CSSコードを眺めながら考えていたのですが、そもそもcheckboxの場合input要素一つのon/offを表現しているのですが、radioボタンだとinput要素2つ(今回は3つ以上は無いものと考えています)のname属性を同一にしつつ、on/offを表現するための根本的な手段が解りません。
また、5種類のinput要素を掲載していたのですが、コード視認性を上げるため、今回実装を目指した2つ(FLAT, FLIP)以外を削除しております。

以下、現在試しているhtmlです。

<li class='tg-list-item'>
  <h4>Flat</h4>
  <input class='tgl tgl-flat-radio' id='radio_on' type='radio' name='radio' value='on' />ON
  <label class='tgl-btn' for='radio_on'></label>
  <input class='tgl tgl-flat-radio' id='radio_off' type='radio' name='radio' value='off' />OFF
  <label class='tgl-btn' for='radio_off'></label>
</li>

以下、加工元のソースになります。

<h2>Toggle Button</h2>
<ul class='tg-list'>
  <li class='tg-list-item'>
    <h4>Flat</h4>
    <input class='tgl tgl-flat' id='cb4' type='checkbox'>
    <label class='tgl-btn' for='cb4'></label>
  </li>
  <li class='tg-list-item'>
    <h4>Flip</h4>
    <input class='tgl tgl-flip' id='cb5' type='checkbox'>
    <label class='tgl-btn' data-tg-off='Nope' data-tg-on='Yeah!' for='cb5'></label>
  </li>
</ul>
.tg-list {
  text-align: center;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;
}

.tg-list-item {
  margin: 0 2em;
}

.tgl {
  display: none;
}
.tgl, .tgl:after, .tgl:before, .tgl *, .tgl *:after, .tgl *:before, .tgl + .tgl-btn {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.tgl::-moz-selection, .tgl:after::-moz-selection, .tgl:before::-moz-selection, .tgl *::-moz-selection, .tgl *:after::-moz-selection, .tgl *:before::-moz-selection, .tgl + .tgl-btn::-moz-selection {
  background: none;
}
.tgl::selection, .tgl:after::selection, .tgl:before::selection, .tgl *::selection, .tgl *:after::selection, .tgl *:before::selection, .tgl + .tgl-btn::selection {
  background: none;
}
.tgl + .tgl-btn {
  outline: 0;
  display: block;
  width: 4em;
  height: 2em;
  position: relative;
  cursor: pointer;
}
.tgl + .tgl-btn:after, .tgl + .tgl-btn:before {
  position: relative;
  display: block;
  content: "";
  width: 50%;
  height: 100%;
}
.tgl + .tgl-btn:after {
  left: 0;
}
.tgl + .tgl-btn:before {
  display: none;
}
.tgl:checked + .tgl-btn:after {
  left: 50%;
}

.tgl-flat + .tgl-btn {
  padding: 2px;
  -webkit-transition: all .2s ease;
  transition: all .2s ease;
  background: #fff;
  border: 4px solid #f2f2f2;
  border-radius: 2em;
}
.tgl-flat + .tgl-btn:after {
  -webkit-transition: all .2s ease;
  transition: all .2s ease;
  background: #f2f2f2;
  content: "";
  border-radius: 1em;
}
.tgl-flat:checked + .tgl-btn {
  border: 4px solid #7FC6A6;
}
.tgl-flat:checked + .tgl-btn:after {
  left: 50%;
  background: #7FC6A6;
}

.tgl-flip + .tgl-btn {
  padding: 2px;
  -webkit-transition: all .2s ease;
  transition: all .2s ease;
  font-family: sans-serif;
  -webkit-perspective: 100px;
  -ms-perspective: 100px;
  perspective: 100px;
}
.tgl-flip + .tgl-btn:after, .tgl-flip + .tgl-btn:before {
  display: inline-block;
  -webkit-transition: all .4s ease;
  transition: all .4s ease;
  width: 100%;
  text-align: center;
  position: absolute;
  line-height: 2em;
  font-weight: bold;
  color: #fff;
  position: absolute;
  top: 0;
  left: 0;
  -webkit-backface-visibility: hidden;
  -ms-backface-visibility: hidden;
  backface-visibility: hidden;
  border-radius: 4px;
}
.tgl-flip + .tgl-btn:after {
  content: attr(data-tg-on);
  background: #02C66F;
  -webkit-transform: rotateY(-180deg);
  -ms-transform: rotateY(-180deg);
  transform: rotateY(-180deg);
}
.tgl-flip + .tgl-btn:before {
  background: #FF3A19;
  content: attr(data-tg-off);
}
.tgl-flip + .tgl-btn:active:before {
  -webkit-transform: rotateY(-20deg);
  -ms-transform: rotateY(-20deg);
  transform: rotateY(-20deg);
}
.tgl-flip:checked + .tgl-btn:before {
  -webkit-transform: rotateY(180deg);
  -ms-transform: rotateY(180deg);
  transform: rotateY(180deg);
}
.tgl-flip:checked + .tgl-btn:after {
  -webkit-transform: rotateY(0);
  -ms-transform: rotateY(0);
  transform: rotateY(0);
  left: 0;
  background: #7FC6A6;
}
.tgl-flip:checked + .tgl-btn:active:after {
  -webkit-transform: rotateY(20deg);
  -ms-transform: rotateY(20deg);
  transform: rotateY(20deg);
}

kei344さんからの助言を基に施したほぼ解決したコード

radioの場合はname属性を同一とし、idを分ける形です。
checkboxの場合は先にhidden要素を配置しておく形で解決となりました。
回答頂いた方々、お忙しい中、有難うございました。
非常に勉強になりました。

<h2>Toggle it!</h2>
<ul class='tg-list'>
  <li class='tg-list-item'>
    <h4>Light (checkbox)</h4>
    <input type='hidden' name='cb_light' value='0' />
    <input class='tgl tgl-light' id='cb-light' type='checkbox' name='cb_light' value='1' />
    <label class='tgl-btn' for='cb-light'></label>
  </li>
  <li class='tg-list-item'>
    <h4>Light (radio)</h4>
    <input class='tgl tgl-light' id='radio-light_on' type='radio' name='radio_light' value='1' />
    <label class='tgl-btn' for='radio-light_on' data-tg-off='OFF' data-tg-on='ON'></label>
    <input class='tgl tgl-light' id='radio-light_off' type='radio' name='radio_light' value='0' checked='checked' />
    <label class='tgl-btn' for='radio-light_off' data-tg-off='OFF' data-tg-on='ON'></label>
  </li>

  <li class='tg-list-item'>
    <h4>iOS 7 (checkbox)</h4>
    <input type='hidden' name='cb_ios' value='0' />
    <input class='tgl tgl-ios' id='cb-ios' type='checkbox' name='cb_ios' value='1' />
    <label class='tgl-btn' for='cb-ios'></label>
  </li>
  <li class='tg-list-item'>
    <h4>iOS 7 (radio)</h4>
    <input class='tgl tgl-ios' id='radio-ios_on' type='radio' name='radio_ios' value='1' />
    <label class='tgl-btn' for='radio-ios_on' data-tg-off='OFF' data-tg-on='ON'></label>
    <input class='tgl tgl-ios' id='radio-ios_off' type='radio' name='radio_ios' value='0' checked='checked' />
    <label class='tgl-btn' for='radio-ios_off' data-tg-off='OFF' data-tg-on='ON'></label>
  </li>

  <li class='tg-list-item'>
    <h4>Skewed (checkbox)</h4>
    <input type='hidden' name='cb_skewed' value='0' />
    <input class='tgl tgl-skewed' id='cb-skewed' type='checkbox' name='cb_skewed' value='1' />
    <label class='tgl-btn' data-tg-off='OFF' data-tg-on='ON' for='cb-skewed'></label>
  </li>
  <li class='tg-list-item'>
    <h4>Skewed (radio)</h4>
    <input class='tgl tgl-skewed' id='radio-skewed_on' type='radio' name='radio_skewed' value='1' />
    <label class='tgl-btn' for='radio-skewed_on' data-tg-off='OFF' data-tg-on='ON'></label>
    <input class='tgl tgl-skewed' id='radio-skewed_off' type='radio' name='radio_skewed' value='0' checked='checked' />
    <label class='tgl-btn' for='radio-skewed_off' data-tg-off='OFF' data-tg-on='ON'></label>
  </li>

  <li class='tg-list-item'>
    <h4>Flat (checkbox)</h4>
    <input type='hidden' name='cb_flat' value='0' />
    <input class='tgl tgl-flat' id='cb-flat' type='checkbox' name='cb_flat' value='1' />
    <label class='tgl-btn' for='cb-flat'></label>
  </li>
  <li class='tg-list-item'>
    <h4>Flat (radio)</h4>
    <input class='tgl tgl-flat' id='radio-flat_on' type='radio' name='radio_flat' value='1' />
    <label class='tgl-btn' for='radio-flat_on'></label>
    <input class='tgl tgl-flat' id='radio-flat_off' type='radio' name='radio_flat' value='0' checked='checked' />
    <label class='tgl-btn' for='radio-flat_off'></label>
  </li>

  <li class='tg-list-item'>
    <h4>Flip (checkbox)</h4>
    <input type='hidden' name='cb_flip' value='0' />
    <input class='tgl tgl-flip' id='cb-flip' type='checkbox' name='cb_flip' value='1' />
    <label class='tgl-btn' data-tg-off='OFF' data-tg-on='ON' for='cb-flip'></label>
  </li>
  <li class='tg-list-item'>
    <h4>Flat (radio)</h4>
    <input class='tgl tgl-flip' id='radio-flip_on' type='radio' name='radio_flip' value='1' />
    <label class='tgl-btn' for='radio-flip_on' data-tg-off='OFF' data-tg-on='ON'></label>
    <input class='tgl tgl-flip' id='radio-flip_off' type='radio' name='radio_flip' value='0' checked='checked' />
    <label class='tgl-btn' for='radio-flip_off' data-tg-off='OFF' data-tg-on='ON'></label>
  </li>
</ul>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2017/05/27 19:30

    ご自身で試されたコードを質問文に追記し、「何」が「どのように」わからないのか、コードのどの部分で詰まっているのかなどを具体的に追記されたほうが回答が望めると思います。

    キャンセル

  • wonda

    2017/05/27 19:48

    失礼致しました。ありがとうございます。

    キャンセル

回答 2

checkベストアンサー

+5

とりあえず下記のようにしたら tgl-flat のスタイルにはなりますよ。

  <input class='tgl tgl-flat tgl-flat-radio' id='radio_on' type='radio' name='radio' value='on' />ON
  <label class='tgl-btn' for='radio_on'></label>
  <input class='tgl tgl-flat tgl-flat-radio' id='radio_off' type='radio' name='radio' value='off' />OFF
  <label class='tgl-btn' for='radio_off'></label>

動くサンプル:https://jsfiddle.net/rLef0oyj/


「なぜこのCSSで切り替えが出来るのか」を考えればラジオボタンでの使用も出来るとは思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/27 21:36

    重ね重ね御助言、有難うございます。
    なるほど。jsでhidden要素を無効化する方法だと、ブラウザでjs無効化されていたらカンマ区切りの値が送信されてしまうと言う事ですね・・。となるとフロント側でご提案頂いた透明ラベル重ねでいくか、もしくはやはりバックエンドで該当するリクエストキーが無い時の処理を入れて対応する方が確実何でしょうかね・・。

    キャンセル

  • 2017/05/27 21:47

    > jsでhidden要素を無効化する方法
    あ、例が悪かったですね。サーバ側がPHPの場合はjsを使わなくても後の値が送られる仕様(だったはず)なのでそのつもりでURL貼っていました、すみません。
    <input type="hidden" id="hidden_checkboxTest1" name="checkboxTest1"/>
    <input type="checkbox" name="checkboxTest1" />
    POSTの受け取りは言語しだいでしたね。ついPHPで考えていました。

    > ブラウザでjs無効化
    その特殊なユーザーために対策をする必要がある案件かどうかによると思います。公共性が高い場合はそこまで考慮すべきだと思いますが、一般的なブラウザではjsが動かないことは無いのでサイトの仕様次第だと思います。

    キャンセル

  • 2017/05/27 22:07

    >POSTの受け取りは言語しだいでしたね。
    なるほど。有難うございます。
    当方もPHPでの相談だったのですが、サンプルURLの結果を鵜呑みにしてしまっていました・・。
    フォーム送信も納得いくまでテストする必要がありますね。

    >特殊なユーザーために対策をする必要がある案件かどうかによると思います。
    有難うございます。
    そのためにはクライアントとの入念なヒアリングが必要ですね!

    今回は本当に有難うございました。
    お陰様で、もっとフロントエンド コーディングのスキルを上げないといけないと思わされました。
    御助言、有難うございました。

    キャンセル

0

radioでCSSだけでやろうとするとonとoff用の2つを用意しないと無理かも^^

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/27 20:09

    そうですね。質問文に補足しているのですが、onとoff用の`input type="radio"`を二つ並べてlabel要素で囲むのか、label要素が2つあった方が良いのか・・といろいろ悩んでいました・・

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる