Как изменить вид checkbox css

I am trying to style a checkbox using the following: But the style is not applied. The ch...

Yikes! All these workarounds have led me to the conclusion that the HTML checkbox kind of sucks if you want to style it.

As a forewarning, this isn’t a CSS implementation. I just thought I’d share the workaround I came up with in case anyone else might find it useful.


I used the HTML5 canvas element.

The upside to this is that you don’t have to use external images and can probably save some bandwidth.

The downside is that if a browser for some reason can’t render it correctly, then there’s no fallback. Though whether this remains an issue in 2017 is debatable.

Update

I found the old code quite ugly, so I decided to give it a rewrite.

Object.prototype.create = function(args){
    var retobj = Object.create(this);

    retobj.constructor(args || null);

    return retobj;
}

var Checkbox = Object.seal({
    width: 0,
    height: 0,
    state: 0,
    document: null,
    parent: null,
    canvas: null,
    ctx: null,

    /*
     * args:
     * name      default             desc.
     *
     * width     15                  width
     * height    15                  height
     * document  window.document     explicit document reference
     * target    this.document.body  target element to insert checkbox into
     */
    constructor: function(args){
        if(args === null)
            args = {};

        this.width = args.width || 15;
        this.height = args.height || 15;
        this.document = args.document || window.document;
        this.parent = args.target || this.document.body;
        this.canvas = this.document.createElement("canvas");
        this.ctx = this.canvas.getContext('2d');

        this.canvas.width = this.width;
        this.canvas.height = this.height;
        this.canvas.addEventListener("click", this.ev_click(this), false);
        this.parent.appendChild(this.canvas);
        this.draw();
    },

    ev_click: function(self){
        return function(unused){
            self.state = !self.state;
            self.draw();
        }
    },

    draw_rect: function(color, offset){
        this.ctx.fillStyle = color;
        this.ctx.fillRect(offset, offset,
                this.width - offset * 2, this.height - offset * 2);
    },

    draw: function(){
        this.draw_rect("#CCCCCC", 0);
        this.draw_rect("#FFFFFF", 1);

        if(this.is_checked())
            this.draw_rect("#000000", 2);
    },

    is_checked: function(){
        return !!this.state;
    }
});

Here’s a working demo.

The new version uses prototypes and differential inheritance to create an efficient system for creating checkboxes. To create a checkbox:

var my_checkbox = Checkbox.create();

This will immediately add the checkbox to the DOM and hook up the events. To query whether a checkbox is checked:

my_checkbox.is_checked(); // True if checked, else false

Also important to note is that I got rid of the loop.

Update 2

Something I neglected to mention in the last update is that using the canvas has more advantages than just making a checkbox that looks however you want it to look. You could also create multi-state checkboxes, if you wanted to.

Object.prototype.create = function(args){
    var retobj = Object.create(this);

    retobj.constructor(args || null);

    return retobj;
}

Object.prototype.extend = function(newobj){
    var oldobj = Object.create(this);

    for(prop in newobj)
        oldobj[prop] = newobj[prop];

    return Object.seal(oldobj);
}

var Checkbox = Object.seal({
    width: 0,
    height: 0,
    state: 0,
    document: null,
    parent: null,
    canvas: null,
    ctx: null,

    /*
     * args:
     * name      default             desc.
     *
     * width     15                  width
     * height    15                  height
     * document  window.document     explicit document reference
     * target    this.document.body  target element to insert checkbox into
     */
    constructor: function(args){
        if(args === null)
            args = {};

        this.width = args.width || 15;
        this.height = args.height || 15;
        this.document = args.document || window.document;
        this.parent = args.target || this.document.body;
        this.canvas = this.document.createElement("canvas");
        this.ctx = this.canvas.getContext('2d');

        this.canvas.width = this.width;
        this.canvas.height = this.height;
        this.canvas.addEventListener("click", this.ev_click(this), false);
        this.parent.appendChild(this.canvas);
        this.draw();
    },

    ev_click: function(self){
        return function(unused){
            self.state = !self.state;
            self.draw();
        }
    },

    draw_rect: function(color, offsetx, offsety){
        this.ctx.fillStyle = color;
        this.ctx.fillRect(offsetx, offsety,
                this.width - offsetx * 2, this.height - offsety * 2);
    },

    draw: function(){
        this.draw_rect("#CCCCCC", 0, 0);
        this.draw_rect("#FFFFFF", 1, 1);
        this.draw_state();
    },

    draw_state: function(){
        if(this.is_checked())
            this.draw_rect("#000000", 2, 2);
    },

    is_checked: function(){
        return this.state == 1;
    }
});

var Checkbox3 = Checkbox.extend({
    ev_click: function(self){
        return function(unused){
            self.state = (self.state + 1) % 3;
            self.draw();
        }
    },

    draw_state: function(){
        if(this.is_checked())
            this.draw_rect("#000000", 2, 2);

        if(this.is_partial())
            this.draw_rect("#000000", 2, (this.height - 2) / 2);
    },

    is_partial: function(){
        return this.state == 2;
    }
});

I modified slightly the Checkbox used in the last snippet so that it is more generic, making it possible to «extend» it with a checkbox that has 3 states. Here’s a demo. As you can see, it already has more functionality than the built-in checkbox.

Something to consider when you’re choosing between JavaScript and CSS.

Old, poorly-designed code

Working Demo

First, set up a canvas

var canvas = document.createElement('canvas'),
    ctx = canvas.getContext('2d'),
    checked = 0; // The state of the checkbox
canvas.width = canvas.height = 15; // Set the width and height of the canvas
document.body.appendChild(canvas);
document.body.appendChild(document.createTextNode(' Togglable Option'));

Next, devise a way to have the canvas update itself.

(function loop(){
  // Draws a border
  ctx.fillStyle = '#ccc';
  ctx.fillRect(0,0,15,15);
  ctx.fillStyle = '#fff';
  ctx.fillRect(1, 1, 13, 13);
  // Fills in canvas if checked
  if(checked){
    ctx.fillStyle = '#000';
    ctx.fillRect(2, 2, 11, 11);
  }
  setTimeout(loop, 1000/10); // Refresh 10 times per second
})();

The last part is to make it interactive. Luckily, it’s pretty simple:

canvas.onclick = function(){
  checked = !checked;
}

This is where you might have problems in IE, due to their weird event handling model in JavaScript.


I hope this helps someone; it definitely suited my needs.

В этой статье подробно разберём процесс кастомной стилизации чекбоксов и радиокнопок с помощью CSS.

Как осуществляется создание кастомного чекбокса или переключателя

Данный процесс осуществляется посредством скрытия стандартного элемента и создания с помощью CSS другого «поддельного», такого как мы хотим.

Но как же это будет работать, если стандартный input скрыть? Это можно выполнить благодаря тому, что в HTML переключить состояние checked можно не только с помощью самого элемента input, но и посредством связанного с ним label.

В HTML связывание label с input выполняется одним из 2 способов:

1. Посредством помещения элемента input в label:

<label>
  <input type="checkbox" name="happy" value="yes">Happy
</label>

2. Посредством задания элементу input атрибута id, а labelfor с таким же значением как у id.

<input type="checkbox" id="happy" name="happy" value="yes">
<label for="happy">Happy</label>

В этой статье мы подробно разберём шаги по кастомизации checkbox и radio, в которых label с input свяжем по 2 варианту. Создание «поддельного» чекбокса выполним с использованием псевдоэлемента ::before, который поместим в label. При этом никакие дополнительные элементы в разметку добавлять не будем.

Создание стильного чекбокса

Процесс замены стандартного вида чекбокса на кастомный осуществим посредством выполнения следующей последовательности шагов.

Шаг 1. Создадим разметку.

<input type="checkbox" class="custom-checkbox" id="happy" name="happy" value="yes">
<label for="happy">Happy</label>

При создании разметки очень важно соблюдать последовательность расположения элементов. Это необходимо, потому что в зависимости от того, как они расположены мы будем составлять выражения для выбора элементов в CSS и назначать им стили.

В этом примере элемент label расположен после input. Связь label с input осуществляется посредством соответствия значения for элемента label с id элемента input.

В примере к элементу input добавлен класс custom-checkbox. Данный класс мы будем использовать при составлении селекторов и тем самым с помощью него определять элементы к которым следует добавить стилизованный чекбокс вместо обычного. Т.е. его присутствие или отсутствие будет определять с каким чекбоксом (со стандартным или поддельным) будет выводится элемент input с type="checkbox".

Вид чекбокса в браузере по умолчанию

Шаг 2. Напишем стили для скрытия стандартного элемента input.

Вид чекбокса после скрытия

.custom-checkbox {
  position: absolute;
  z-index: -1;
  opacity: 0;
}

Мы не будем использовать display: none, а установим ему стили, с помощью которых уберём его из потока (position: absolute), поместим его ниже существующих элементов (z-index: -1), а также сделаем его полностью прозрачным (opacity: 0). Зачем это нужно? Это нам необходимо для того, чтобы мы могли получить состояние фокуса, а затем стилизовать «подделный» checkbox или radio, когда он будет находиться в нём.

Шаг 3. Создадим поддельный чекбокс.

Вид кастомного чекбокса

.custom-checkbox+label {
  display: inline-flex;
  align-items: center;
  user-select: none;
}
.custom-checkbox+label::before {
  content: '';
  display: inline-block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  flex-grow: 0;
  border: 1px solid #adb5bd;
  border-radius: 0.25em;
  margin-right: 0.5em;
  background-repeat: no-repeat;
  background-position: center center;
  background-size: 50% 50%;
}

Создание «поддельного» чекбокса выполним с помощью псевдоэлемента ::before. Посредством CSS зададим ему размеры (в данном случае 1emx1em), а затем нарисуем его с помощью border: 1px solid #adb5bd. Свойства начинающие со слова background будут определять положение самого флажка (когда checkbox будет в состоянии checked).

Первое правило необходимо для вертикального центрирования флажка и надписи к нему. Это действие в примере выполнено через CSS Flexbox.

Шаг 4. Создадим стили при нахождении элемента в состоянии checked.

Вид стилизованного чекбокса в состоянии checked

.custom-checkbox:checked+label::before {
  border-color: #0b76ef;
  background-color: #0b76ef;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e");
}

В этом коде при получении элементом состояния checked применим к псевдоэлементу ::before находящемуся в label стили, посредством которых установим цвет границы, цвет фону и фоновую картинку (флажок) в формате svg.

Шаг 5. Добавим код для стилизации чекбокса при нахождении его в состояниях hover, active, focus и disabled.

Вид кастомного чекбокса в состояниях hover, active, focus и disabled

/* стили при наведении курсора на checkbox */
.custom-checkbox:not(:disabled):not(:checked)+label:hover::before {
  border-color: #b3d7ff;
}
/* стили для активного состояния чекбокса (при нажатии на него) */
.custom-checkbox:not(:disabled):active+label::before {
  background-color: #b3d7ff;
  border-color: #b3d7ff;
}
/* стили для чекбокса, находящегося в фокусе */
.custom-checkbox:focus+label::before {
  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
/* стили для чекбокса, находящегося в фокусе и не находящегося в состоянии checked */
.custom-checkbox:focus:not(:checked)+label::before {
  border-color: #80bdff;
}
/* стили для чекбокса, находящегося в состоянии disabled */
.custom-checkbox:disabled+label::before {
  background-color: #e9ecef;
}

Открыть пример

Разработка кастомного переключателя

Стилизация переключателя (input с type="radio") выполняется аналогично, т.е. посредством тех же шагов которые мы применяли при кастомизации чекбокса.

Вид стилизованного чекбокса в браузере по умолчанию и в состоянии checked

Итоговый набор стилей для кастомного оформления input с type="radio":

<style>
  /* для элемента input c type="radio" */
  .custom-radio {
    position: absolute;
    z-index: -1;
    opacity: 0;
  }
  /* для элемента label связанного с .custom-radio */
  .custom-radio+label {
    display: inline-flex;
    align-items: center;
    user-select: none;
  }
  /* создание в label псевдоэлемента  before со следующими стилями */
  .custom-radio+label::before {
    content: '';
    display: inline-block;
    width: 1em;
    height: 1em;
    flex-shrink: 0;
    flex-grow: 0;
    border: 1px solid #adb5bd;
    border-radius: 50%;
    margin-right: 0.5em;
    background-repeat: no-repeat;
    background-position: center center;
    background-size: 50% 50%;
  }
  /* стили при наведении курсора на радио */
  .custom-radio:not(:disabled):not(:checked)+label:hover::before {
    border-color: #b3d7ff;
  }
  /* стили для активной радиокнопки (при нажатии на неё) */
  .custom-radio:not(:disabled):active+label::before {
    background-color: #b3d7ff;
    border-color: #b3d7ff;
  }
  /* стили для радиокнопки, находящейся в фокусе */
  .custom-radio:focus+label::before {
    box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
  }
  /* стили для радиокнопки, находящейся в фокусе и не находящейся в состоянии checked */
  .custom-radio:focus:not(:checked)+label::before {
    border-color: #80bdff;
  }
  /* стили для радиокнопки, находящейся в состоянии checked */
  .custom-radio:checked+label::before {
    border-color: #0b76ef;
    background-color: #0b76ef;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
  }
  /* стили для радиокнопки, находящейся в состоянии disabled */
  .custom-radio:disabled+label::before {
    background-color: #e9ecef;
  }
</style>

<input class="custom-radio" name="color" type="radio" id="color-green" value="green">
<label for="color-green">Green</label>

Открыть пример

Ещё примеры по кастомизации checkbox и label

В этом разделе представлены следующие примеры:

  • оформление чекбокса, когда input расположен в label
  • оформление переключателя, когда input расположен в label

1. Стилизация checkbox, когда input расположен в label.

HTML разметка:

<label class="custom-checkbox">
  <input type="checkbox" value="value-1">
  <span>Indigo</span>
</label>

CSS код:

/* для элемента input c type="checkbox" */
.custom-checkbox>input {
  position: absolute;
  z-index: -1;
  opacity: 0;
}

/* для элемента label, связанного с .custom-checkbox */
.custom-checkbox>span {
  display: inline-flex;
  align-items: center;
  user-select: none;
}

/* создание в label псевдоэлемента before со следующими стилями */
.custom-checkbox>span::before {
  content: '';
  display: inline-block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  flex-grow: 0;
  border: 1px solid #adb5bd;
  border-radius: 0.25em;
  margin-right: 0.5em;
  background-repeat: no-repeat;
  background-position: center center;
  background-size: 50% 50%;
}

/* стили при наведении курсора на checkbox */
.custom-checkbox>input:not(:disabled):not(:checked)+span:hover::before {
  border-color: #b3d7ff;
}

/* стили для активного чекбокса (при нажатии на него) */
.custom-checkbox>input:not(:disabled):active+span::before {
  background-color: #b3d7ff;
  border-color: #b3d7ff;
}

/* стили для чекбокса, находящегося в фокусе */
.custom-checkbox>input:focus+span::before {
  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}

/* стили для чекбокса, находящегося в фокусе и не находящегося в состоянии checked */
.custom-checkbox>input:focus:not(:checked)+span::before {
  border-color: #80bdff;
}

/* стили для чекбокса, находящегося в состоянии checked */
.custom-checkbox>input:checked+span::before {
  border-color: #0b76ef;
  background-color: #0b76ef;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e");
}

/* стили для чекбокса, находящегося в состоянии disabled */
.custom-checkbox>input:disabled+span::before {
  background-color: #e9ecef;
}

Открыть пример

2. Стилизация radio, когда input расположен в label.

HTML разметка:

<label class="custom-radio">
  <input type="radio" name="color" value="indigo">
  <span>Indigo</span>
</label>

CSS код:

/* для элемента input c type="radio" */
.custom-radio>input {
  position: absolute;
  z-index: -1;
  opacity: 0;
}

/* для элемента label связанного с .custom-radio */
.custom-radio>span {
  display: inline-flex;
  align-items: center;
  user-select: none;
}

/* создание в label псевдоэлемента  before со следующими стилями */
.custom-radio>span::before {
  content: '';
  display: inline-block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  flex-grow: 0;
  border: 1px solid #adb5bd;
  border-radius: 50%;
  margin-right: 0.5em;
  background-repeat: no-repeat;
  background-position: center center;
  background-size: 50% 50%;
}

/* стили при наведении курсора на радио */
.custom-radio>input:not(:disabled):not(:checked)+span:hover::before {
  border-color: #b3d7ff;
}

/* стили для активной радиокнопки (при нажатии на неё) */
.custom-radio>input:not(:disabled):active+span::before {
  background-color: #b3d7ff;
  border-color: #b3d7ff;
}

/* стили для радиокнопки, находящейся в фокусе */
.custom-radio>input:focus+span::before {
  box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}

/* стили для радиокнопки, находящейся в фокусе и не находящейся в состоянии checked */
.custom-radio>input:focus:not(:checked)+span::before {
  border-color: #80bdff;
}

/* стили для радиокнопки, находящейся в состоянии checked */
.custom-radio>input:checked+span::before {
  border-color: #0b76ef;
  background-color: #0b76ef;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
}

/* стили для радиокнопки, находящейся в состоянии disabled */
.custom-radio>input:disabled+span::before {
  background-color: #e9ecef;
}

Открыть пример

Оформление элементов формы — это старая проблема. Ситуация несомненно улучшается, но финала пока не видно. С появлением псевдо-контейнеров :after и :before стало возможным без дополнительных элементов и скриптов кастомизировать элемент INPUT:CHECKBOX.

<input type=«checkbox» id=«checkbox-id» />

<label for=«checkbox-id»>Чекбокс как есть</label>

В разных браузерах этот элемент будет выглядеть по разному. Chrome, Opera, IE, Yandex и прочие — будут по мере сил и фантазии разработчиков выводить checkbox с собственным оформлением.

Квадрат и галочку нельзя изменить стандартными стилями вроде:

// это работать не будет

input[type=«checkbox»] {

  border: 1px solid #f00;

  background: #f00;

  borderradius: 5;

}

Поэтому стоит задача полностью заменить вывод стандартного элемента на свой, и мы сделаем это, используя только CSS.

План действий такой:

  1. Скрываем вывод чек-бокса;
  2. Формируем нужный внешний вид чекбокса в псевдо — элементе label:before;
  3. Дополнительные стили формируют внешний вид текущего статуса.

Важно, чтобы элемент Label был связан с чекбокс (через параметр for), тогда нажатие на метку передаётся на связанный элемент, и все работает как нужно без дополнительных скриптов.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

/* прячем input checkbox */

input[type=«checkbox»] {

  display: none;

}

/* стили для метки */

label {

color: #000;

  cursor: default;

  fontweight: normal;

  lineheight: 30px;

  padding: 10px 0;

  verticalalign: middle;

}

/* формируем внешний вид чекбокса в псевдоэлементе before */

label:before {

  content: » «;

  color: #000;

  display: inlineblock;

  font: 20px/30px Arial;

  marginright: 15px;

  position: relative;

  textalign: center;

  textindent: 0px;

  width: 30px;

  height: 30px;

  background: #FFF;

  border: 1px solid #e3e3e3;

  borderimage: initial;

  verticalalign: middle;

}

/* вариации внешнего вида в зав-ти от статуса checkbox */

/* checked */

input:checked + label:before {

  content: «x»;

}

/* disabled */

input:disabled + label:before {

  background: #eee;

  color: #aaa;

}

Теперь внешний вид становится везде одинаковым и выглядит вот так:

Как видите для вывода галочки я использовал просто символ «x» из шрифта Arial. Далее вы можете сами решать как выглядит контейнер и галочка.

Я к примеру использую шрифт awesome, в котором есть литера галочки.

Вот тот же CSS с использованием FontAwesome:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

input[type=«checkbox»] {

display: none;

}

label {

color: #000;

cursor: default;

fontweight: normal;

lineheight: 30px;

padding: 10px 0;

verticalalign: middle;

}

label:before {

content: » «;

color: #000;

display: inlineblock;

/* шрифт Awesome*/

font: 20px/30px FontAwesome;

marginright: 15px;

position: relative;

textalign: center;

textindent: 0px;

width: 30px;

height: 30px;

background: #FFF;

border: 1px solid #e3e3e3;

borderimage: initial;

verticalalign: middle;

}

input:checked + label:before {

/* глифон — галочка */

content: «f00c»;

}

input:disabled + label:before {

background: #eee;

color: #aaa;

}

Так выглядит checkbox с галочкой из набора иконок Awesome.

Написать комментарий


Данная запись опубликована в 27.12.2017 17:23 и размещена в Танцы с CSS.
Вы можете перейти в конец страницы и оставить ваш комментарий.

Мало букафф? Читайте есчо !

Эффект тряски элемента на сайте при наведении с помощью CCS3

Октябрь 23, 2015 г.

В последнее время как то кучно пошло у меня использование CCS3 анимации. Продолжаю делиться шаблонами. Сегодня рассмотрим анимацию, которая, запускаясь при наведении, имитирует дрожание элемента. Её можно подключать и в других случаях (не только при наведении). …

Читать

И снова переносы в CSS

Ноябрь 30, 2021 г.

Да, вновь тема переносов, т.к. я уже писал небольшую статью, но еще раз возвращаюсь к данной теме с некоторыми новыми подробностями. Итак — разрыв слова, перенос текста на новую строку — рассмотрим, какие директивы даёт нам CSS для управления поведением …

Читать

Наверняка вы задумались о том, как можно изменить стандартный вид флажков (чекбоксов), чтобы они выглядели привлекательней с учетом дизайна вашего сайта или задач одной конкретной страницы. В этой статье вы найдете ряд практических примеров, которые помогут вам стилизовать элементы <input type="checkbox">. Для начала разберем пример, который имеет вид переключателя. Давайте посмотрим, как можно стилизовать флажки на примере, который в html-разметке содержит только <input type="checkbox"> и <label>:

<input type=«checkbox» id=«demo1» checked>

<label for=«demo1» dataonlabel=«Вкл.» dataofflabel=«Выкл.»></label>

<input type=«checkbox» id=«demo2»>

<label for=«demo2» dataonlabel=«Да» dataofflabel=«Нет»></label>

Сам пример в действии:

Теперь рассмотрим CSS-стили:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

label { margin: 2em;}

input { display: none;}

input+label,

input+label::before,

input+label::after {

-webkit-transition: all .2s;

transition: all .2s;

}

input+label {

display: inline-block;

position: relative;

width: 130px;

height: 50px;

border-radius: 25px;

cursor: pointer;

}

input+label::before {

display: block;

content: attr(data-off-label);

position: absolute;

top: 15px;

right: 10px;

color: #fff;

font-family: Arial, sans-serif;

font-size: 18px;

}

input+label::after {

content: »;

position: absolute;

top: 2px;

left: 2px;

width: 44px;

height: 44px;

background-color: #fff;

border-radius: 50%;

}

input:checked+label::before {

content: attr(data-on-label);

left: 14px;

right: auto;

color: #fff;

}

input:checked+label::after {

left: 83px;

background-color: #f7f7f7;

}

#demo1+label { background-color: #ccc; }

#demo1+label::before { color: #999; }

#demo1:checked+label { background-color: #3498db; }

#demo1:checked+label::before { color: #fff; }

#demo2+label { background-color: #e74c3c; }

#demo2:checked+label { background-color: #1abc9c; }

Если проанализировать код CSS, то видно, что элемент input мы прячем (свойство display: none), а все остальные стили прописаны для элемента label, а также псевдоэлементов label::before и label::after. Изменения внешнего вида также осуществляются для псевдокласса :checked, который имеет смысл использовать для флажков и радио-кнопок.

Еще ряд похожих вариантов с анимацией вам предлагает Himalaya Singh в своем примере.

See the Pen Pure CSS Toggle Buttons | ON-OFF Switches by Himalaya Singh (@himalayasingh) on CodePen.18892

И еще один пример:

See the Pen Simple CSS Checkbox by Tristan White (@triss90) on CodePen.18892

Примеры стилизации флажков с ресурса codepen.io

Как работает стилизация

В этом примере видно, где расположен флажок, который обычно скрывается с помощью свойства display: none, и как стилизованы label. Откройте вкладку CSS и проанализируйте код.

See the Pen [Pure CSS] Delightful Checkbox Animation by Dylan Raga (@dylanraga) on CodePen.18892

Простое решение для флажков и переключателей от Jon Kantner.

See the Pen CSS Checkboxes and Radio Buttons by Jon Kantner (@jkantner) on CodePen.18892

Близкие к стандартным варианты флажков, переключателей и выпадающих списков от Kenan Yusuf

See the Pen Completely CSS: Custom checkboxes, radio buttons and select boxes by Kenan Yusuf (@KenanYusuf) on CodePen.18892

Зачеркивание при выборе флажка с анимацией

See the Pen Animated Fill and Strikethrough Checkboxes by Jon Kantner (@jkantner) on CodePen.18892

Несколько интересных решений для флажков и переключателей от Brad Bodine

See the Pen CSS3 Checkbox Styles by Brad Bodine (@bbodine1) on CodePen.18892

Несколько похожих переключений состояний чекбокса от Olivia Ng

See the Pen Toggles by Elen (@ambassador)
on CodePen.0

Разные виды переключателей от Mauricio Allende

See the Pen Pure CSS toggle buttons by Elen (@ambassador) on CodePen.0

Анимированное переключение состояний флажка в виде пилюли

See the Pen Pill Switch 💊 by Elen (@ambassador) on CodePen.18892

Круглая кнопка с анимацией от mandycodestoo

See the Pen 100dayscss-66 by @mandycodestoo (@mandycodestoo) on CodePen.18892

Анимация текста флажков и радио-кнопок от Raúl Barrera

See the Pen Pure CSS Fancy Checkbox/Radio by Raúl Barrera (@raubaca) on CodePen.18892

Подсветка текста label + анимация выбора чекбокса от Adam Quinlan

See the Pen chippy checkbox inputs by Adam Quinlan (@quinlo) on CodePen.18892

Анимированные флажки с изменением цвета на основе css-переменных от Stas Melnikov

See the Pen #CodePenChallenge | Pure CSS Checkboxes by Stas Melnikov (@melnik909) on CodePen.18892

Анимация флажков с переворотом

See the Pen Flip checkbox by Elen (@ambassador) on CodePen.18892

Анимация флажков и переключателей в стиле Material Design от Matt Sisto

See the Pen CSS «Ripple/Wave» checkbox and radio button by Matt Sisto (@msisto) on CodePen.18892

Перекатывающийся шарик от Jon Kantner

Вариант 1

See the Pen Toy Toggle Switch by Jon Kantner (@jkantner) on CodePen.18892

Вариант 2 со скрепкой

See the Pen Paper Clip Toggle Switch by Jon Kantner (@jkantner) on CodePen.18892

Карандаш для отметки выбора флажка

Еще один вариант анимации от Jon Kantner, но с появлением карандаша. Отличное решение для тестов, например.

See the Pen Pencil and Paper Checkboxes by Jon Kantner (@jkantner) on CodePen.18892

Меняем цветовую схему переключателем

Автор Jon Kantner предлагает вашему вниманию вариант кода, при котором клик на чекбоксе меняет цвет фона.

Вариант 1

See the Pen Toggle Switch with Rolling Label by Jon Kantner (@jkantner) on CodePen.18892

Вариант 2

See the Pen Light/Dark Mode Toggle With Curtain Effect by Jon Kantner (@jkantner) on CodePen.18892

Переключатель энергии

See the Pen Blocky Toggle Switch by Jon Kantner (@jkantner) on CodePen.18892

Реализация аккордеона на чистом CSS с использованием чекбоксов от Alex Bergin

See the Pen CSS + HTML only Accordion Element by Alex Bergin (@abergin) on CodePen.18892

Переключатель цены от Aniruddha Banerjee

See the Pen Pricing Card Design by Aniruddha Banerjee (@imanirudh1) on CodePen.0

Выбор группы иконок от Håvard Brynjulfsen

See the Pen Checkbox group styled as tiles by Håvard Brynjulfsen (@havardob) on CodePen.0

Использование переключателя для показа скрытого контента

Скрытый checkbox нужен для отображения блока с информацией, которая не видна изначально. Автор Lisi.

See the Pen Expand Information by Lisi (@lisilinhart)on CodePen.0

Сложные примеры

Оказывается, флажки (чекбоксы) можно стилизовать так, что пользователи вряд ли догадаются о том, что используют именно эти элементы.

Шестеренки в переключателе с анимацией

Автор leimapapa 

See the Pen ⚙️ Giant Gear Toggle ⚙️ by leimapapa (@leimapapa) on CodePen.0

Флажок-выключатель

Отличная стилизация <input type="checkbox"> в виде выключателя с внутренней подсветкой от Yoav Kadosh.

See the Pen Realistic Red Switch (Pure CSS) by Yoav Kadosh (@ykadosh) on CodePen.18892

Лампа-переключатель

Вариант попроще внешне от Jon Kantner, но в коде вы найдете очень меого правил.

See the Pen Light Bulb Toggle Switch by Jon Kantner (@jkantner) on CodePen.18892

Флажок-переключатель

Настоящий переключатель от Jon Kantner. Здесь использован не только CSS, но и JS-код.

See the Pen Skeuomorphic Lever Checkbox by Jon Kantner (@jkantner) on CodePen.18892

Еще один вариант 3D-переключателя

Автор Yoav Kadosh

See the Pen 3D Orange Switch (Pure CSS) by Yoav Kadosh (@ykadosh) on CodePen.0

3D-трансформации с анимацией

Глядя на этот пример, понимаешь, что стилизация переключателей — это наименьшее из того, что сделал автор Ivan Grozdic . Отличный вариант для туристического сайта в плане выбора услуг.

See the Pen Pricing — pure css — #16 by Ivan Grozdic (@ig_design) on CodePen.18892

Пример генератора пароля с использованием флажков

See the Pen Random Password Generator — HTML | CSS | JS by Sikriti Dakua (@dev_loop) on CodePen.18892

ToDo List (список дел) от Will Boyd

Интересно то, что при отметке чекбокса вы получаете список дел с подсчетом сделанных и несделанных заданий на основе только лишь CSS, совсем без JavaScript-кода, за счет использования свойства counter-increment и свойства order Flexbox-модели.

See the Pen Checkbox Trickery: To-Do List by Will Boyd (@lonekorean) on CodePen.18892

И еще один ToDo List от Daniel Ramos

Только CSS, без JavaScript

See the Pen To do List + CSS by Daniel Ramos (@DanielRamos)  on CodePen.0

Бонус. Невключаемый чекбох

Для тех, кто дочитал до конца — бонус — чекбокс, который нельзя оставить включенным, так как вы рассердите мишку. Он даже рычать умеет и хмурить брови. Наслаждайтесь ))) Написано на React. Автор Jhey.

See the Pen Impossible Checkbox v2 🐻 by Jhey (@jh3y)
on CodePen.0

Просмотров: 10 672

Yikes! All these workarounds have led me to the conclusion that the HTML checkbox kind of sucks if you want to style it.

As a forewarning, this isn’t a CSS implementation. I just thought I’d share the workaround I came up with in case anyone else might find it useful.


I used the HTML5 canvas element.

The upside to this is that you don’t have to use external images and can probably save some bandwidth.

The downside is that if a browser for some reason can’t render it correctly, then there’s no fallback. Though whether this remains an issue in 2017 is debatable.

Update

I found the old code quite ugly, so I decided to give it a rewrite.

Object.prototype.create = function(args){
    var retobj = Object.create(this);

    retobj.constructor(args || null);

    return retobj;
}

var Checkbox = Object.seal({
    width: 0,
    height: 0,
    state: 0,
    document: null,
    parent: null,
    canvas: null,
    ctx: null,

    /*
     * args:
     * name      default             desc.
     *
     * width     15                  width
     * height    15                  height
     * document  window.document     explicit document reference
     * target    this.document.body  target element to insert checkbox into
     */
    constructor: function(args){
        if(args === null)
            args = {};

        this.width = args.width || 15;
        this.height = args.height || 15;
        this.document = args.document || window.document;
        this.parent = args.target || this.document.body;
        this.canvas = this.document.createElement("canvas");
        this.ctx = this.canvas.getContext('2d');

        this.canvas.width = this.width;
        this.canvas.height = this.height;
        this.canvas.addEventListener("click", this.ev_click(this), false);
        this.parent.appendChild(this.canvas);
        this.draw();
    },

    ev_click: function(self){
        return function(unused){
            self.state = !self.state;
            self.draw();
        }
    },

    draw_rect: function(color, offset){
        this.ctx.fillStyle = color;
        this.ctx.fillRect(offset, offset,
                this.width - offset * 2, this.height - offset * 2);
    },

    draw: function(){
        this.draw_rect("#CCCCCC", 0);
        this.draw_rect("#FFFFFF", 1);

        if(this.is_checked())
            this.draw_rect("#000000", 2);
    },

    is_checked: function(){
        return !!this.state;
    }
});

Here’s a working demo.

The new version uses prototypes and differential inheritance to create an efficient system for creating checkboxes. To create a checkbox:

var my_checkbox = Checkbox.create();

This will immediately add the checkbox to the DOM and hook up the events. To query whether a checkbox is checked:

my_checkbox.is_checked(); // True if checked, else false

Also important to note is that I got rid of the loop.

Update 2

Something I neglected to mention in the last update is that using the canvas has more advantages than just making a checkbox that looks however you want it to look. You could also create multi-state checkboxes, if you wanted to.

Object.prototype.create = function(args){
    var retobj = Object.create(this);

    retobj.constructor(args || null);

    return retobj;
}

Object.prototype.extend = function(newobj){
    var oldobj = Object.create(this);

    for(prop in newobj)
        oldobj[prop] = newobj[prop];

    return Object.seal(oldobj);
}

var Checkbox = Object.seal({
    width: 0,
    height: 0,
    state: 0,
    document: null,
    parent: null,
    canvas: null,
    ctx: null,

    /*
     * args:
     * name      default             desc.
     *
     * width     15                  width
     * height    15                  height
     * document  window.document     explicit document reference
     * target    this.document.body  target element to insert checkbox into
     */
    constructor: function(args){
        if(args === null)
            args = {};

        this.width = args.width || 15;
        this.height = args.height || 15;
        this.document = args.document || window.document;
        this.parent = args.target || this.document.body;
        this.canvas = this.document.createElement("canvas");
        this.ctx = this.canvas.getContext('2d');

        this.canvas.width = this.width;
        this.canvas.height = this.height;
        this.canvas.addEventListener("click", this.ev_click(this), false);
        this.parent.appendChild(this.canvas);
        this.draw();
    },

    ev_click: function(self){
        return function(unused){
            self.state = !self.state;
            self.draw();
        }
    },

    draw_rect: function(color, offsetx, offsety){
        this.ctx.fillStyle = color;
        this.ctx.fillRect(offsetx, offsety,
                this.width - offsetx * 2, this.height - offsety * 2);
    },

    draw: function(){
        this.draw_rect("#CCCCCC", 0, 0);
        this.draw_rect("#FFFFFF", 1, 1);
        this.draw_state();
    },

    draw_state: function(){
        if(this.is_checked())
            this.draw_rect("#000000", 2, 2);
    },

    is_checked: function(){
        return this.state == 1;
    }
});

var Checkbox3 = Checkbox.extend({
    ev_click: function(self){
        return function(unused){
            self.state = (self.state + 1) % 3;
            self.draw();
        }
    },

    draw_state: function(){
        if(this.is_checked())
            this.draw_rect("#000000", 2, 2);

        if(this.is_partial())
            this.draw_rect("#000000", 2, (this.height - 2) / 2);
    },

    is_partial: function(){
        return this.state == 2;
    }
});

I modified slightly the Checkbox used in the last snippet so that it is more generic, making it possible to «extend» it with a checkbox that has 3 states. Here’s a demo. As you can see, it already has more functionality than the built-in checkbox.

Something to consider when you’re choosing between JavaScript and CSS.

Old, poorly-designed code

Working Demo

First, set up a canvas

var canvas = document.createElement('canvas'),
    ctx = canvas.getContext('2d'),
    checked = 0; // The state of the checkbox
canvas.width = canvas.height = 15; // Set the width and height of the canvas
document.body.appendChild(canvas);
document.body.appendChild(document.createTextNode(' Togglable Option'));

Next, devise a way to have the canvas update itself.

(function loop(){
  // Draws a border
  ctx.fillStyle = '#ccc';
  ctx.fillRect(0,0,15,15);
  ctx.fillStyle = '#fff';
  ctx.fillRect(1, 1, 13, 13);
  // Fills in canvas if checked
  if(checked){
    ctx.fillStyle = '#000';
    ctx.fillRect(2, 2, 11, 11);
  }
  setTimeout(loop, 1000/10); // Refresh 10 times per second
})();

The last part is to make it interactive. Luckily, it’s pretty simple:

canvas.onclick = function(){
  checked = !checked;
}

This is where you might have problems in IE, due to their weird event handling model in JavaScript.


I hope this helps someone; it definitely suited my needs.

Yikes! All these workarounds have led me to the conclusion that the HTML checkbox kind of sucks if you want to style it.

As a forewarning, this isn’t a CSS implementation. I just thought I’d share the workaround I came up with in case anyone else might find it useful.


I used the HTML5 canvas element.

The upside to this is that you don’t have to use external images and can probably save some bandwidth.

The downside is that if a browser for some reason can’t render it correctly, then there’s no fallback. Though whether this remains an issue in 2017 is debatable.

Update

I found the old code quite ugly, so I decided to give it a rewrite.

Object.prototype.create = function(args){
    var retobj = Object.create(this);

    retobj.constructor(args || null);

    return retobj;
}

var Checkbox = Object.seal({
    width: 0,
    height: 0,
    state: 0,
    document: null,
    parent: null,
    canvas: null,
    ctx: null,

    /*
     * args:
     * name      default             desc.
     *
     * width     15                  width
     * height    15                  height
     * document  window.document     explicit document reference
     * target    this.document.body  target element to insert checkbox into
     */
    constructor: function(args){
        if(args === null)
            args = {};

        this.width = args.width || 15;
        this.height = args.height || 15;
        this.document = args.document || window.document;
        this.parent = args.target || this.document.body;
        this.canvas = this.document.createElement("canvas");
        this.ctx = this.canvas.getContext('2d');

        this.canvas.width = this.width;
        this.canvas.height = this.height;
        this.canvas.addEventListener("click", this.ev_click(this), false);
        this.parent.appendChild(this.canvas);
        this.draw();
    },

    ev_click: function(self){
        return function(unused){
            self.state = !self.state;
            self.draw();
        }
    },

    draw_rect: function(color, offset){
        this.ctx.fillStyle = color;
        this.ctx.fillRect(offset, offset,
                this.width - offset * 2, this.height - offset * 2);
    },

    draw: function(){
        this.draw_rect("#CCCCCC", 0);
        this.draw_rect("#FFFFFF", 1);

        if(this.is_checked())
            this.draw_rect("#000000", 2);
    },

    is_checked: function(){
        return !!this.state;
    }
});

Here’s a working demo.

The new version uses prototypes and differential inheritance to create an efficient system for creating checkboxes. To create a checkbox:

var my_checkbox = Checkbox.create();

This will immediately add the checkbox to the DOM and hook up the events. To query whether a checkbox is checked:

my_checkbox.is_checked(); // True if checked, else false

Also important to note is that I got rid of the loop.

Update 2

Something I neglected to mention in the last update is that using the canvas has more advantages than just making a checkbox that looks however you want it to look. You could also create multi-state checkboxes, if you wanted to.

Object.prototype.create = function(args){
    var retobj = Object.create(this);

    retobj.constructor(args || null);

    return retobj;
}

Object.prototype.extend = function(newobj){
    var oldobj = Object.create(this);

    for(prop in newobj)
        oldobj[prop] = newobj[prop];

    return Object.seal(oldobj);
}

var Checkbox = Object.seal({
    width: 0,
    height: 0,
    state: 0,
    document: null,
    parent: null,
    canvas: null,
    ctx: null,

    /*
     * args:
     * name      default             desc.
     *
     * width     15                  width
     * height    15                  height
     * document  window.document     explicit document reference
     * target    this.document.body  target element to insert checkbox into
     */
    constructor: function(args){
        if(args === null)
            args = {};

        this.width = args.width || 15;
        this.height = args.height || 15;
        this.document = args.document || window.document;
        this.parent = args.target || this.document.body;
        this.canvas = this.document.createElement("canvas");
        this.ctx = this.canvas.getContext('2d');

        this.canvas.width = this.width;
        this.canvas.height = this.height;
        this.canvas.addEventListener("click", this.ev_click(this), false);
        this.parent.appendChild(this.canvas);
        this.draw();
    },

    ev_click: function(self){
        return function(unused){
            self.state = !self.state;
            self.draw();
        }
    },

    draw_rect: function(color, offsetx, offsety){
        this.ctx.fillStyle = color;
        this.ctx.fillRect(offsetx, offsety,
                this.width - offsetx * 2, this.height - offsety * 2);
    },

    draw: function(){
        this.draw_rect("#CCCCCC", 0, 0);
        this.draw_rect("#FFFFFF", 1, 1);
        this.draw_state();
    },

    draw_state: function(){
        if(this.is_checked())
            this.draw_rect("#000000", 2, 2);
    },

    is_checked: function(){
        return this.state == 1;
    }
});

var Checkbox3 = Checkbox.extend({
    ev_click: function(self){
        return function(unused){
            self.state = (self.state + 1) % 3;
            self.draw();
        }
    },

    draw_state: function(){
        if(this.is_checked())
            this.draw_rect("#000000", 2, 2);

        if(this.is_partial())
            this.draw_rect("#000000", 2, (this.height - 2) / 2);
    },

    is_partial: function(){
        return this.state == 2;
    }
});

I modified slightly the Checkbox used in the last snippet so that it is more generic, making it possible to «extend» it with a checkbox that has 3 states. Here’s a demo. As you can see, it already has more functionality than the built-in checkbox.

Something to consider when you’re choosing between JavaScript and CSS.

Old, poorly-designed code

Working Demo

First, set up a canvas

var canvas = document.createElement('canvas'),
    ctx = canvas.getContext('2d'),
    checked = 0; // The state of the checkbox
canvas.width = canvas.height = 15; // Set the width and height of the canvas
document.body.appendChild(canvas);
document.body.appendChild(document.createTextNode(' Togglable Option'));

Next, devise a way to have the canvas update itself.

(function loop(){
  // Draws a border
  ctx.fillStyle = '#ccc';
  ctx.fillRect(0,0,15,15);
  ctx.fillStyle = '#fff';
  ctx.fillRect(1, 1, 13, 13);
  // Fills in canvas if checked
  if(checked){
    ctx.fillStyle = '#000';
    ctx.fillRect(2, 2, 11, 11);
  }
  setTimeout(loop, 1000/10); // Refresh 10 times per second
})();

The last part is to make it interactive. Luckily, it’s pretty simple:

canvas.onclick = function(){
  checked = !checked;
}

This is where you might have problems in IE, due to their weird event handling model in JavaScript.


I hope this helps someone; it definitely suited my needs.

Несколько примеров как изменить внешний вид чекбоксов с помощью CSS, изображений и немного JS.

1

Метод «Checkbox Hack»

Основан на связи <label> и помещенного в него инпута, т.е. по клику на него, инпут будет менять свое состояние.

<label>
	<input type="checkbox">
	Checkbox
</label>

HTML

Стоит заменить что в некоторых старых браузерах (например Safari) такой приём не работает и требует добавление атрибутов for у <label> и id у чекбокса.

<label for="element">
	<input type="checkbox" id="element">
	Checkbox
</label>

HTML

В зависимости от состояния чекбокса :checked, :disabled и :focus, следующему за ним элементу, например <span>, можно задавать стили с помощью селектора «+».

<label>
	<input type="checkbox">
	<span>Checkbox</span>
</label>

HTML

/* Dafault */
label input[type=checkbox] + span {
	...
}

/* Focus */
label input[type=checkbox]:focus + span {
	...
}

/* Checked */
label input[type=checkbox]:checked + span {
	...
}

/* Disabled */
label input[type=checkbox]:disabled + span {
	...
}
label input[type=checkbox]:disabled:checked + span {
	...
}

CSS

Сам чекбокс скрывается, но без использования display: none, что бы оставить функциональность фокуса.

label input[type=checkbox] {
	position: absolute;
	z-index: -1;
	opacity: 0;
	display: block;
	width: 0;
	height: 0;
}

CSS

По умолчанию, фокус появляется при клике на элемент, что не очень и нужно. Оставить выделение при фокусе только при нажатии клавиши Tab можно с помощью JQuery, добавляя класс focused родительскому элементу.

$(window).keyup(function(e){
	var target = $('label input[type=checkbox]:focus');
	if (e.keyCode == 9 && $(target).length){
		$(target).parent().addClass('focused');
	}
});

$('label input[type=checkbox]').focusout(function(){
	$(this).parent().removeClass('focused');
});

JS

Пример №1

В первом примере понадобятся два изображения (обычный и отмеченный), для ускорения прорисовки можно использовать спрайты, но тогда не сделать плавную смену при переключении (transition background).

HTML-разметка:

<label class="checkbox-other">
	<input type="checkbox" checked>
	<span>Checkbox #1</span>
</label>

<label class="checkbox-other">
	<input type="checkbox">
	<span>Checkbox #2</span>
</label>

<label class="checkbox-other">
	<input type="checkbox" disabled>
	<span>Checkbox #3</span>
</label>

<label class="checkbox-other">
	<input type="checkbox" checked disabled>
	<span>Checkbox #4</span>
</label>

HTML

Фокус по клавише Tab:

$(window).keyup(function(e){
	var target = $('.checkbox-other input:focus');
	if (e.keyCode == 9 && $(target).length){
		$(target).parent().addClass('focused');
	}
});

$('.checkbox-other input').focusout(function(){
	$(this).parent().removeClass('focused');
});

JS

CSS-стили:

.checkbox-other {
	display: block;
	margin: 0 0 10px 0;
	cursor: pointer;
	user-select: none;
	position: relative;
}
.checkbox-other input[type=checkbox] {
	position: absolute;
	z-index: -1;
	opacity: 0;
	display: block;
	width: 0;
	height: 0;
}
.checkbox-other span {
	display: inline-block;
	position: relative; 
	padding: 0 0 0 35px; 
	line-height: 22px;    
}
.checkbox-other span:before {
	content: "";
	display: inline-block;
	width: 22px;
	height: 22px;
	position: absolute;
	left: 0;
	top: 0;
	transition: background 0.3s ease;
	background: url(/checkbox-1.png) 0 0 no-repeat;
}

/* Checked */
.checkbox-other input[type=checkbox]:checked + span:before {
	background-image: url(/checkbox-2.png);
}

/* Focus */
.focused span:before {
	box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}

/* Hover */
.checkbox-other span:hover:before {
	filter: brightness(110%);
}

/* Active */
.checkbox-other span:active:before {
	filter: brightness(80%);
}

/* Disabled */
.checkbox-other input[type=checkbox]:disabled + span {
	color: #666;
	cursor: default;
}
.checkbox-other input[type=checkbox]:disabled + span:before {
	filter: grayscale(100%);
	opacity: 0.6;
}

CSS

Результат:

Пример №2

Подходит для случаев, когда галка выходит за края элемента. HTML-разметка и JS-код остается прежними.

.checkbox-other {
	display: block;
	margin: 0 0 10px 0;
	cursor: pointer;
	user-select: none;
	position: relative;
}
.checkbox-other input[type=checkbox] {
	position: absolute;
	z-index: -1;
	opacity: 0;
	display: block;
	width: 0;
	height: 0;
}
.checkbox-other span {
	display: inline-block;
	position: relative; 
	padding: 0 0 0 35px; 
	line-height: 22px;    
}
.checkbox-other span:before {
	content: "";
	display: inline-block;
	width: 22px;
	height: 22px;
	position: absolute;
	left: 0;
	top: 0;
	background: url(/checkbox-3.png) 0 0 no-repeat;
}

/* Checked */
.checkbox-other input[type=checkbox] + span:after {
	content: "";	
	opacity: 0;
	transition: opacity 0.3s ease;
}
.checkbox-other input[type=checkbox]:checked + span:after {
	display: inline-block;
	width: 22px;
	height: 22px;
	position: absolute;
	left: 4px;
	top: -5px;
	background: url(/checkbox-4.png) 0 0 no-repeat;
	opacity: 1;
}

/* Focus */
.focused span:before {
	box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}

/* Hover */
.checkbox-other span:hover:after {
	filter: brightness(110%);
}

/* Active */
.checkbox-other span:active:before,
.checkbox-other span:active:after {
	filter: brightness(80%);
}

/* Disabled */
.checkbox-other input[type=checkbox]:disabled + span {
	color: #666;
	cursor: default;
}
.checkbox-other input[type=checkbox]:disabled + span:before,
.checkbox-other input[type=checkbox]:disabled + span:after {
	filter: grayscale(100%);
	opacity: 0.6;
}

CSS

Результат:

Пример №3

Вариант с использованием символа галочки – ✓ или эмоджи ✔.

.checkbox-other {
	display: block;
	margin: 0 0 10px 0;
	line-height: 22px;
	cursor: pointer;
	user-select: none;
	position: relative;
}
.checkbox-other input[type=checkbox] {
	position: absolute;
	z-index: -1;
	opacity: 0;
	display: block;
	width: 0;
	height: 0;
}
.checkbox-other span {
	display: inline-block;
	position: relative; 
	padding: 0 0 0 35px; 
	line-height: 22px;    
}
.checkbox-other span:before {
	content: "";
	display: inline-block;
	width: 20px;
	height: 20px;
	position: absolute;
	left: 0;
	top: 0;
	border: 1px solid #2B7335;
	box-shadow: inset 0 0 3px #8a8a8a;
}

/* Checked */
.checkbox-other input[type=checkbox] + span:after {
	content: "";	
	opacity: 0;
	transition: opacity 0.3s ease;
}
.checkbox-other input[type=checkbox]:checked + span:after {
	content: "✓";
	color: green;
	font-size: 30px;
	font-weight: 900;
	position: absolute;
	left: 2px;
	top: -2px;
	opacity: 1;
}

/* Focus */
.focused span:before {
	box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}

/* Hover */
.checkbox-other span:hover:after {
	filter: brightness(110%);
}

/* Active */
.checkbox-other span:active:before,
.checkbox-other span:active:after {
	filter: brightness(80%);
}

/* Disabled */
.checkbox-other input[type=checkbox]:disabled + span {
	color: #666;
	cursor: default;
}
.checkbox-other input[type=checkbox]:disabled + span:before,
.checkbox-other input[type=checkbox]:disabled + span:after {
	filter: grayscale(100%);
	opacity: 0.6;
}

CSS

2

CSS свойство appearance

Пока нестандартезированое свойство -webkit-appearance: none отключает стандартное оформление элемнта формы, но сохраняет его функциональность, тем самым появляется возможность задать ему любые стили, но без псевдосвойст :before и :after. Полное описание на developer.mozilla.org.

<label class="checkbox-other">
	<input type="checkbox" checked> Checkbox #1
</label>

<label class="checkbox-other">
	<input type="checkbox"> Checkbox #2
</label>

<label class="checkbox-other">
	<input type="checkbox" disabled> Checkbox #3
</label>

<label class="checkbox-other">
	<input type="checkbox" checked disabled> Checkbox #4
</label>

HTML

.checkbox-other {
	display: block;
	margin: 0 0 10px 0;
	line-height: 22px;  
}
.checkbox-other input[type=checkbox] {
	-webkit-appearance: none;
	-moz-appearance: none;
	display: inline-block;
	width: 22px;
	height: 22px;
	margin: 0 5px 0 0;
	padding: 0;
	vertical-align: top;
	outline: none;
	transition: background 0.3s ease;
	background: url(/checkbox-1.png) 0 0 no-repeat;
	cursor: pointer;
}

/* Checked */
.checkbox-other input[type=checkbox]:checked {
	background-image: url(/checkbox-2.png);
}

/* Focus */
.focused input[type=checkbox] {
	box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}

/* Hover */
.checkbox-other input[type=checkbox]:hover {
	filter: brightness(110%);
}

/* Active */
.checkbox-other input[type=checkbox]:active {
	filter: brightness(80%);
}

/* Disabled */
.checkbox-other input[type=checkbox]:disabled {
	color: #666;
	cursor: default;
}
.checkbox-other input[type=checkbox]:disabled {
	filter: grayscale(100%);
	opacity: 0.6;
}

CSS

Свойство appearance поддерживается всеми современными брузерами. В старых брауезерах, чекбокбокс будет выводится как обычный.

Data on support for the css-appearance feature across the major browsers from caniuse.com

22.04.2020, обновлено 21.02.2021

Другие публикации

Отметить или снять все чекбоксы в таблице

Мини JQuery плагин позволяет отметить или снять одним кликом чекбоксы в таблицах и отметить чекбокс по клику на сроку…

Checkbox или radiobutton в меню dropdowns

Проблема в том что если вставить чекбокс, радиокнопку в меню dropdowns Bootstrap и кликнув по ним, меню сразу…

Раскрывающийся многоуровневый список

В данном примере описано как вывести многоуровневый список checkbox и radio button из БД с помощью PHP функций…

Селект с чекбоксами

Селект с множественным выбором (select multiple) весьма не удобен, при выборе часто забываешь нажимать сtrl и все сбрасывается. В место него можно использовать чекбоксы в выпадающем списке.

Стилизация input file

Примеры изменения вида стандартного поля для загрузки файлов input type file с помощью CSS и JS.

Contenteditable – текстовый редактор

Если добавить атрибут contenteditable к элементу, его содержимое становится доступно для редактирования пользователю, а…

Мы уже много говорили о базовом CSS, немного о препроцессорах, современных командах и гридах. Теперь посмотрим на вложенности и зависимости — полезный инструмент для веб-разработки в реальном мире. 

Основой нашего кода станет вот этот кусок, в частности — знак плюса:

.checkbox__input:checked + .checkbox__icon .tick {...}

Плюс означает, что стиль применяется к элементам класса .checkbox__icon .tick, которые идут в HTML-коде сразу после отмеченного элемента checkbox__input.

Также в коде будет использоваться такое заклинание: 

.check-group > * + * {...}

Но его так запросто не объяснишь, листайте дальше. 

Что делаем

Допустим, мы делаем интерфейс интернет-пиццерии и хотим добавить конфигуратор начинки. Нам нужно, чтобы пользователь мог поставить галочки возле ингредиентов. При этом важно, чтобы всё выглядело красиво (а не как в стандартном исполнении браузера). 

Классический дизайн чекбоксов

Если мы сделаем это просто на чекбоксах, мы получим мелкие и едва кликабельные штучки. Вот их сейчас мы будем прокачивать, чтобы они были крупными и анимированными: 

Делаем красивые чекбоксы с анимацией
<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Начинка для пиццы</title>

</head>
<body>

<h1>
Что добавить в пиццу?
</h1>
<p>
<input type="checkbox" name="in1"> Оливки </input>
</p>
<p>
<input type="checkbox" name="in2"> Пепперони </input>
</p>
<p>
<input type="checkbox" name="in3"> Каперсы </input>
</p>
<p>
<input type="checkbox" name="in4"> Помидоры </input>
</p>
</body>
</html>

Подключаем нормализатор и файл со стилями

Чтобы чекбоксы выглядели одинаково во всех браузерах, начнём с нормализатора CSS. Это специальный набор стилей, который приводит содержимое нашей страницы к единому виду в каждом браузере. 

Подключается нормализатор так:

<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">

Заодно сразу подключим файл со стилями. Он пока пустой:

<link rel="stylesheet" href="style.css">

Делаем красивые чекбоксы с анимацией
Из-за нормализатора сломались поля, но это не главная наша проблема

Меняем внешний вид чекбокса

Чтобы сделать анимацию отмечания галочки, мы пойдём на хитрость: отрисуем все элементы вручную с помощью SVG-графики и потом используем её для анимации.

Для этого мы поступим так:

  1. Используем тег <label>, чтобы потом можно было подписать чекбокс, и сразу напишем id элемента, который нужно будет подписать. Этим элементом станет чекбокс. 
  2. Внутри этого тега разместим тег <input>, который создаст нам чекбокс. 
  3. Укажем для чекбокса стиль, чтобы настроить его внешний вид, и id, чтобы подпись поняла, к чему именно она относится. 
  4. Ниже добавим SVG-область, в которой нарисуем сразу рамку и галочку.
  5. Рамка будет видимой сразу, а видимостью галочки мы будем управлять через стили.
  6. Добавим саму подпись чекбокса в теге <span>.
<!DOCTYPE html>
<html lang="ru" >
<head>
  <meta charset="UTF-8">
  <title>Начинка для пиццы</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  <link rel="stylesheet" href="style.css">

</head>
<body>

<h1>
Что добавить в пиццу?
</h1>

<!-- создаём подпись и указываем, к какому элементу она относится -->
  <label for="myCheckbox01" class="checkbox">

    <!-- размещаем обычный чекбокс и задаём ему нужный класс -->
    <!-- также указываем id, чтобы подпись смогла найти этот инбокс -->
    <input class="checkbox__input" type="checkbox" id="myCheckbox01">
    
    <!-- готовим виртуальное пространство для рисования -->
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <!-- рисуем красивую рамку чекбокса -->
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <!-- сразу делаем красивую галочку, но пока делаем её невидимой -->
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>

    <!-- подписываем наш чекбокс -->
    <span class="checkbox__label">Оливки</span>
  </label>
</body>
</html>
Делаем красивые чекбоксы с анимацией

Видно, что у нас появился новый дизайн чекбокса и галочки, но сломались размеры. Всё дело в том, что мы не настроили стили для этих элементов. Добавим это в файл style.css — читайте комментарии, если что-то будет непонятно:

/* общие настройки для всей страницы */
body {
  /* отступы */
  margin: 2em;
  /* цвет фона */
  background: #f0f0f0;
  /* добавляем адаптивное расположение элементов */
  display: flex;
  /* расстояние между элементами */
  gap: 2rem;
  /* разрешаем увеличивать размеры областей в зависимости от размеров элемента */
  flex-wrap: wrap;
  align-items: flex-start;
}

/* настройки для всего элемента с чекбоксом */
.checkbox {
  /* меняем внешний вид курсора */
  cursor: pointer;
  /* выравниваем элементы по центру */
  display: flex;
  align-items: center;
}

/* отдельные настройки для самого чекбокса */
.checkbox__input {
  /* устанавливаем абсолютное позиционирование */
  position: absolute;
  /* задаём высоту и ширину */
  width: 1.375em;
  height: 1.375em;
  /* делаем чекбокс непрозрачным, чтобы скрыть исходный элемент и заменить его потом нарисованным */
  opacity: 0;
  /* меняем внешний вид курсора */
  cursor: pointer;
}

/* настройки для SVG-иконки */
.checkbox__icon {
  /* размеры совпадают с размерами скрытого чекбокса */
  width: 1.375em;
  height: 1.375em;
  /* убираем ограничение по наименьшей ширине блока */
  flex-shrink: 0;
  /* разрешаем отображать содержимое за пределами блока */
  overflow: visible;
}

/* общие настройки для нового чекбокса и галочки */
.checkbox__icon .tick {
  /* рисовать будем всё отрезками по 20 пикселей */
  stroke-dasharray: 20px;
  /* но сместим следующие отрезки тоже на 20 пикселей, чтобы получить сплошные линии */
  stroke-dashoffset: 20px;
  /* это даст нам плавную анимацию отрисовки галочки */
  transition: stroke-dashoffset 0.2s ease-out;
}

/* настройки для подписи чекбокса */
.checkbox__label {
  /* добавляем отступ слева */
  margin-left: 0.5em;
}
Делаем красивые чекбоксы с анимацией

Стало лучше, появился новый красивый чекбокс, но галочку в него поставить пока нельзя — мы не настроили стили для этого. Исправим это, добавив новые стили в файл:

/* включаем возможность поставить галочку */
.checkbox__input:checked + .checkbox__icon .tick {
  /* убираем смещение для отрезков, чтобы включить анимацию галочки */
  stroke-dashoffset: 0;
}

👉 Обратите внимание на плюс в этой записи. Он означает, что этот стиль применяется к элементам класса .checkbox__icon .tick, которые идут в HTML-коде сразу после отмеченного элемента checkbox__input. Если между элементами с этими классами вставить какой-то другой тег, то ничего не сработает. Такой подход позволяет тонко управлять поведением элементов на странице. 

Делаем красивые чекбоксы с анимацией

Добавляем остальные чекбоксы

Теперь, когда мы научились ставить красивые чекбоксы с анимированными галочками, вернёмся в HTML-код и добавим остальные варианты для пиццы. Делаем это простым копированием и вставкой. Единственное, что нужно не забыть поменять, — числа в id у чекбоксов:

<!DOCTYPE html>
<html lang="ru" >
<head>
  <meta charset="UTF-8">
  <title>Начинка для пиццы</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  <link rel="stylesheet" href="style.css">

</head>
<body>

<h1>
Что добавить в пиццу?
</h1>

  <!-- создаём подпись и указываем, к какому элементу она относится -->
  <label for="myCheckbox01" class="checkbox">

    <!-- размещаем обычный чекбокс и задаём ему нужный класс -->
    <!-- также указываем id, чтобы подпись смогла найти этот инбокс -->
    <input class="checkbox__input" type="checkbox" id="myCheckbox01">
    
    <!-- готовим виртуальное пространство для рисования -->
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <!-- рисуем красивую рамку чекбокса -->
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <!-- сразу делаем красивую галочку, но пока делаем её невидимой -->
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>

    <!-- подписываем наш чекбокс -->
    <span class="checkbox__label">Оливки</span>
  </label>

  <label for="myCheckbox02" class="checkbox">
    <input class="checkbox__input" type="checkbox" id="myCheckbox02">
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>
    <span class="checkbox__label">Пепперони</span>
  </label>

   <label for="myCheckbox03" class="checkbox">
    <input class="checkbox__input" type="checkbox" id="myCheckbox03">
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>
    <span class="checkbox__label">Каперсы</span>
  </label>

   <label for="myCheckbox04" class="checkbox">
    <input class="checkbox__input" type="checkbox" id="myCheckbox04">
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>
    <span class="checkbox__label">Помидоры</span>
  </label>

</body>
</html>
Делаем красивые чекбоксы с анимацией

Теперь у нас есть все нужные чекбоксы, только они стоят в ряд, а нам хорошо бы их сделать друг под другом. А ещё у нас до сих пор нет автоподсчёта отмеченных галочек.

Объединяем чекбоксы

Самый простой способ что-то объединить в HTML — использовать тег <div>. Объединим наши чекбоксы с помощью него и зададим отдельный класс для оформления:

<!-- общий блок для всех чекбоксов -->
<div class="check-group">
<!-- здесь находится код наших чекбоксов -->
</div>

А теперь пропишем стили в CSS-файле:

.check-group {
  /* делаем группе отдельный фон */
  background: #fff;
  /* ограничиваем ширину блока, чтобы он не расползался */
  max-width: 13rem;
  /* добавляем отступы */
  padding: 1.5rem;
  /* делаем красивое скругление и тень */
  border-radius: 0.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 10, 0.2);
  /* сразу добавляем два счётчика, они понадобятся для подсчёта выбранных элементов */
  counter-reset: total;
  counter-reset: checked;
}

/* делаем отступы внутри группы */
.check-group > * + * {
  margin-top: 0.75rem;
}
Делаем красивые чекбоксы с анимацией

Самая магия происходит в строке .check-group > * + *, и вот что она означает:

  1. Символ «больше» означает, что правило будет относиться к каким-то элементам, которые лежат внутри тега с классом .check-group.
  2. Звёздочка означает, что это правило относится ко всем элементам, которые лежат внутри.
  3. Плюс означает, что предыдущее правило применяется, только если предыдущий (то есть любой вложенный) и следующий (то есть тоже любой вложенный) элементы идут друг за другом.
  4. Вторая звёздочка означает, что следующий элемент тоже может быть любым.

Если перевести это всё с айтишного на русский, то будет звучать примерно так:

«Отодвинь все вложенные элементы друг от друга на такое-то расстояние. От верха с низом не отодвигай, потому для них это правило не работает».

Ради интереса можете удалить плюс и вторую звёздочку и посмотреть, как изменится внешний вид группы.

Считаем количество отмеченных галочек

Если вы смотрели CSS-код из предыдущего этапа, то обратили внимание на счётчики, которые мы задаём прямо в CSS. Современный CSS получил поддержку таких мини-переменных, которые могут считать количество отображённых элементов. 

Чтобы увеличить значение счётчика на единицу, используют команду  counter-increment. Используем её, чтобы посчитать сначала количество всех чекбоксов:

/* подсчитываем количество всех чекбоксов */
.check-group .checkbox {
  counter-increment: total;
}

А потом считаем количество отмеченных галочек:

/* считаем только отмеченные галочки */
.check-group input[type=checkbox]:checked {
  counter-increment: checked;
}

Последнее, что нам осталось сделать, — вывести на экран итоговое количество выбранных добавок.

Добавляем вывод с результатами

Чтобы вывести строку с результатом, внутри общего блока в самом конце разместим строку:

<div class="check-group__result">Выбрано:</div>

Теперь нам нужно научить станицу правильно заполнять её содержимое. Для этого используем два стиля — просто для блока с этой надписью, чтобы она выглядела солидно, и второй стиль с псевдоклассом :after, который сработает после отрисовки остальных стилей:

/* настраиваем внешний вид строки с результатом */
.check-group__result {
  /* делаем жирный шрифт */
  font-weight: bold;
  /* немного отступаем сверху */
  padding-top: 0.75rem;
  /* рисуем тонкую линию над текстом */
  border-top: 1px solid rgba(0, 0, 0, 0.2);
}

/* обрабатываем результаты */
.check-group__result:after {
  /* добавляем строку со значениями счётчиков */
  content: counter(checked) " / " counter(total);
  /* добавляем отступ слева */
  padding-left: 1ch;
}
Делаем красивые чекбоксы с анимацией

Мы получили анимацию и динамическое управление контентом на странице средствами CSS. Пока что это не слишком функционально, потому что мы не отправляем эти данные никуда на сервер и не берём с клиента деньги за пиццу, но зато CSS. Есть чем гордиться 🙂

Готовый результат можно посмотреть на странице проекта.

<!DOCTYPE html>
<html lang="ru" >
<head>
  <meta charset="UTF-8">
  <title>Начинка для пиццы</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  <link rel="stylesheet" href="style.css">

</head>
<body>

<h1>
Что добавить в пиццу?
</h1>
<!-- общий блок для всех чекбоксов -->
<div class="check-group">
  <!-- создаём подпись и указываем, к какому элементу она относится -->
  <label for="myCheckbox01" class="checkbox">

    <!-- размещаем обычный чекбокс и задаём ему нужный класс -->
    <!-- также указываем id, чтобы подпись смогла найти этот инбокс -->
    <input class="checkbox__input" type="checkbox" id="myCheckbox01">
    
    <!-- готовим виртуальное пространство для рисования -->
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <!-- рисуем красивую рамку чекбокса -->
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <!-- сразу делаем красивую галочку, но пока делаем её невидимой -->
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>

    <!-- подписываем наш чекбокс -->
    <span class="checkbox__label">Оливки</span>
  </label>

  <label for="myCheckbox02" class="checkbox">
    <input class="checkbox__input" type="checkbox" id="myCheckbox02">
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>
    <span class="checkbox__label">Пепперони</span>
  </label>

   <label for="myCheckbox03" class="checkbox">
    <input class="checkbox__input" type="checkbox" id="myCheckbox03">
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>
    <span class="checkbox__label">Каперсы</span>
  </label>

   <label for="myCheckbox04" class="checkbox">
    <input class="checkbox__input" type="checkbox" id="myCheckbox04">
    <svg class="checkbox__icon" viewBox="0 0 22 22">
      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
    </svg>
    <span class="checkbox__label">Помидоры</span>
  </label>

  <!-- считаем и выводим результаты -->
  <div class="check-group__result">Выбрано:</div>
</div>


  
</body>
</html>
/* общие настройки для всей страницы */
body {
  /* отступы */
  margin: 2em;
  /* цвет фона */
  background: #f0f0f0;
  /* добавляем адаптивное расположение элементов */
  display: flex;
  /* расстояние между элементами */
  gap: 2rem;
  /* разрешаем увеличивать размеры областей в зависимости от размеров элемента */
  flex-wrap: wrap;
  align-items: flex-start;
}

/* настройки для всего элемента с чекбоксом */
.checkbox {
  /* меняем внешний вид курсора */
  cursor: pointer;
  /* выравниваем элементы по центру */
  display: flex;
  align-items: center;
}

/* отдельные настройки для самого чекбокса */
.checkbox__input {
  /* устанавливаем абсолютное позиционирование */
  position: absolute;
  /* задаём высоту и ширину */
  width: 1.375em;
  height: 1.375em;
  /* делаем чекбокс непрозрачным, чтобы скрыть исходный элемент и заменить его потом нарисованным */
  opacity: 0;
  /* меняем внешний вид курсора */
  cursor: pointer;
}

/* настройки для SVG-иконки */
.checkbox__icon {
  /* размеры совпадают с размерами скрытого чекбокса */
  width: 1.375em;
  height: 1.375em;
  /* убираем ограничение по наименьшей ширине блока */
  flex-shrink: 0;
  /* разрешаем отображать содержимое за пределами блока */
  overflow: visible;
}

/* общие настройки для нового чекбокса и галочки */
.checkbox__icon .tick {
  /* рисовать будем всё отрезками по 20 пикселей */
  stroke-dasharray: 20px;
  /* но сместим начало всех отрезков тоже на 20 пикселей, чтобы пока галочка не рисовалась */
  stroke-dashoffset: 20px;
  /* это даст нам плавную анимацию отрисовки галочки */
  transition: stroke-dashoffset 0.2s ease-out;
}

/* настройки для подписи чекбокса */
.checkbox__label {
  /* добавляем отступ слева */
  margin-left: 0.5em;
}

/* включаем возможность поставить галочку */
.checkbox__input:checked + .checkbox__icon .tick {
  /* убираем смещение для отрезков, чтобы включить анимацию галочки */
  stroke-dashoffset: 0;
}


.check-group {
  /* делаем группе отдельный фон */
  background: #fff;
  /* ограничиваем ширину блока, чтобы он не расползался */
  max-width: 13rem;
  /* добавляем отступы */
  padding: 1.5rem;
  /* делаем красивое скругление и тень */
  border-radius: 0.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 10, 0.2);
  /* сразу добавляем два счётчика, они понадобятся для подсчёта выбранных элементов */
  counter-reset: total;
  counter-reset: checked;
}

/* делаем отступы внутри группы */
.check-group > * + * {
  margin-top: 0.75rem;
}

/* подсчитываем количество всех чекбоксов */
.check-group .checkbox {
  counter-increment: total;
}

/* считаем только отмеченные галочки */
.check-group input[type=checkbox]:checked {
  counter-increment: checked;
}

/* настраиваем внешний вид строки с результатом */
.check-group__result {
  /* делаем жирный шрифт */
  font-weight: bold;
  /* немного отступаем сверху */
  padding-top: 0.75rem;
  /* рисуем тонкую линию над текстом */
  border-top: 1px solid rgba(0, 0, 0, 0.2);
}

/* обрабатываем результаты */
.check-group__result:after {
  /* добавляем строку со значениями счётчиков */
  content: counter(checked) " / " counter(total);
  /* добавляем отступ слева */
  padding-left: 1ch;
}

Вёрстка:

Кирилл Климентьев

Понравилась статья? Поделить с друзьями:
  • Как изменить виброзвонок на айфоне
  • Как изменить вибро на айфоне 12
  • Как изменить вибрацию на часах apple watch
  • Как изменить вибрацию на хуавей
  • Как изменить вибрацию на хонор 8х