Boutons CSS on/off II

J'ai essayé il y a 3 mois de reproduire en HTML/CSS un bouton de type « on/off » de l'environnement de bureau Cinnamon. J'ai utilisé un élément button alors qu'il aurait été plus logique de prendre une case à cocher. Nouvelle expérimentation...

Rendu de différents types de bouton « on/off ».
<!-- checkbox classique -->
<p><input type="checkbox" id="check"><label for="check">Some setting</label></p>
<!-- checkbox on-off sans libellé -->
<p><input class="on-off" type="checkbox" id="on-off"><label for="on-off">Some setting</label></p>
<!-- checkbox on-off avec libellé -->
<p><input class="on-off-label" type="checkbox" id="on-off-l"><label for="on-off-l">Some setting</label></p>
<!-- checkbox on-off avec libellé à gauche -->
<p><input class="on-off-label-left" type="checkbox" id="on-off-lf"><label for="on-off-lf">Some setting</label></p>
Code HTML.
.on-off,
.on-off-label,
.on-off-label-left {
    border: 0;
    padding: 0;
    margin: 0;
    visibility: hidden;
}
.on-off + label,
.on-off-label + label,
.on-off-label-left + label {
    position: relative;
    /* typo */
    font: 10px/18px arial, sans-serif;
    text-transform: uppercase;
    cursor: pointer;
    /* box */
    display: inline-block;
    padding: 0;
    height: 20px;
    margin: 0 0 0 -14px;
}
.on-off + label {
    font-size: 0;
    width: 60px;
}
.on-off + label:before,
.on-off-label + label:before,
.on-off-label-left + label:after {
    /* typo */
    content: "off";
    font-size: 10px;
    text-align: right;
    /* box */
    display: inline-block;
    width: 60px;
    border-width: 1px;
    border-style: solid;
    padding: 0 5px;
    -webkit-border-radius: 5px;
       -moz-border-radius: 5px;
            border-radius: 5px;
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
         -o-box-sizing: border-box;
             box-sizing: border-box;
    /* colors */
    color: #ccc;
    text-shadow: 1px 1px 3px #333;
    border-color: rgba(0,0,0,0.2);
    background-color: #666;
    -webkit-box-shadow: inset 0 0 1px #5C5C5C;
       -moz-box-shadow: inset 0 0 1px #5C5C5C;
         -o-box-shadow: inset 0 0 1px #5C5C5C;
            box-shadow: inset 0 0 1px #5C5C5C;
    background-image: -webkit-gradient(linear, left top, left bottom, from(#373737), to(#4f4f4f));
    background-image: -webkit-linear-gradient(center top , #373737, #4f4f4f);
    background-image:    -moz-linear-gradient(center top , #373737, #4f4f4f);
    background-image:     -ms-linear-gradient(center top , #373737, #4f4f4f);
    background-image:      -o-linear-gradient(center top , #373737, #4f4f4f);
    background-image:         linear-gradient(center top , #373737, #4f4f4f);
}
.on-off-label + label:before {
    margin: 0 5px 0 0;
}
.on-off-label-left + label:after {
    margin: 0 0 0 5px;
}
.on-off + label:after,
.on-off-label + label:after,
.on-off-label-left + label:before {
    /* typo */
    content:"|||";
    font-size: 10px;
    text-align:center;
    line-height: 14px;
    /* box */
    display:inline-block;
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
         -o-box-sizing: border-box;
            box-sizing: border-box;
    width: 30px;
    height: 20px;
    padding: 0;
    border-width: 1px;
    border-style: solid;
    /* position */
    position: absolute;
    top: 0;
    /* colors */
    color: #979797;
    text-shadow: 1px 1px #fff;
    border-color: #e9e9e9 #d1d1d1 #a1a1a1 #bebebe;
    background-color: #ccc;
    -webkit-border-radius: 5px;
       -moz-border-radius: 5px;
            border-radius: 5px;
    -webkit-box-shadow: 0 0 1px 1px rgba(0,0,0,0.5);
       -moz-box-shadow: 0 0 1px 1px rgba(0,0,0,0.5);
         -o-box-shadow: 0 0 1px 1px rgba(0,0,0,0.5);
            box-shadow: 0 0 1px 1px rgba(0,0,0,0.5);
    background-image: -webkit-gradient(linear, left top, left bottom, from(#d4d4d4), to(#a4a4a4));
    background-image: -webkit-linear-gradient(top , #d4d4d4, #a4a4a4);
    background-image:    -moz-linear-gradient(top , #d4d4d4, #a4a4a4);
    background-image:     -ms-linear-gradient(top , #d4d4d4, #a4a4a4);
    background-image:      -o-linear-gradient(top , #d4d4d4, #a4a4a4);
    background-image:         linear-gradient(top , #d4d4d4, #a4a4a4);
}
.on-off + label:after,
.on-off-label + label:after {
    left: -1px;
    -webkit-transition: left 0.2s;
       -moz-transition: left 0.2s;
        -ms-transition: left 0.2s;
         -o-transition: left 0.2s;
            transition: left 0.2s;
}
.on-off-label-left + label:before {
    right: 30px;
    -webkit-transition: right 0.2s;
       -moz-transition: right 0.2s;
        -ms-transition: right 0.2s;
         -o-transition: right 0.2s;
            transition: right 0.2s;
}
.on-off:checked + label:before,
.on-off-label:checked + label:before,
.on-off-label-left:checked + label:after {
    content: "on";
    text-align: left;
}
.on-off:checked + label:after,
.on-off-label:checked + label:after {
    left: 30px;
    -webkit-transition: left 0.2s;
       -moz-transition: left 0.2s;
        -ms-transition: left 0.2s;
         -o-transition: left 0.2s;
            transition: left 0.2s;
}
.on-off-label-left:checked + label:before {
    right: 0;
    -webkit-transition: right 0.2s;
       -moz-transition: right 0.2s;
        -ms-transition: right 0.2s;
         -o-transition: right 0.2s;
            transition: right 0.2s;
}
Code CSS.
  • Tester sous Firefox 13, Internet Explorer 9, Web 3.4.1 (WebKit 1.8.1), Opera 12, Chrome.
  • Seul Firefox supporte les transitions sur les pseudo-éléments.
  • Internet Explorer 9 ne comprend pas les gradients et se contente d'appliquer la couleur de fond.

L'unique contrainte HTML est de positionner le label après l'élément input de type « checkbox ». Le fait de devoir préciser l'attribut « for » sur les label n'est pas une contrainte ; il s'agit simplement d'écrire correctement du HTML.