Добро пожаловать в блог, где важны слова.

Тут я частенько публикую в открытым доступе полезные материаллы и готовые решения для повседневных задач по 1С-Битрикс и Битрикс24, а также затрагиваю темы всё что связано с сайтостроением

BX библиотека

BX библиотека

Cтатья на стадии заполнения


BX.findFormElements

Функция принимает один параметр, передав id формы, он найдет все элементы формы (input, select, textarea, button и др) и вернет его в виде массива. Также в параметр можно передать class или id тега div, результат выполнения будет таким же.
BX.ready(function () {
    BX.bindDelegate(document.body, 'click', {
        tagName: 'button'
    }, function () {
        // Получаем id кнопки
        const nameId = this.getAttribute("id");
        // Место для вставки с результатами
        const text = document.getElementById("resultCount");

        // Функция вставки результата
        function setContent(object, content) {
            object.innerHTML = " ";
            object.insertAdjacentHTML("beforeend", content);
        }

        // Кнопка - Подсчитать у всей формы
        if (nameId === "findFormElements") {
            const count = BX.findFormElements(BX("userForm"));
            setContent(text, "Элементов у формы: " + count.length)
        }
        // Кнопка - Подсчитать у блока "Телефоны"
        if (nameId === "findFormElements-phones") {
            const nameClass = document.querySelector(".phones")
            const count = BX.findFormElements(nameClass);
            setContent(text, "Элементов у блока Телефоны: " + count.length)
        }
    })
})
<div class="userForm__descr">Данную функцию удобно использовать когда веб-форма большая, где элементы отображаются по
    группам. Например легко обратиться к определенной группе элементов и ими мунипулировать.
</div>
<form class="userForm" id="userForm">
    <fieldset class="group personal-data">
        <legend>Личные данные</legend>
        <div class="userForm__field">
            <label class="userForm__label">Профессия</label>
            <input class="userForm__text" type="text" name="profession">
        </div>
        <div class="userForm__field">
            <label class="userForm__label">Пол</label>
            <select name="gender">
                <option value="none">Не выбран</option>
                <option value="M">Мужской</option>
                <option value="F">Женский</option>
            </select>
        </div>
        <div class="userForm__field">
            <label class="userForm__label">Дата рождения</label>
            <input class="userForm__text" name="date" type="date">
        </div>
    </fieldset>
    <fieldset class="group phones">
        <legend>Телефоны</legend>
        <div class="userForm__field">
            <label class="userForm__label">Телефон</label>
            <input class="userForm__text" type="text" value="" name="phone">
        </div>
        <div class="userForm__field">
            <label class="userForm__label">Факс</label>
            <input class="userForm__text" type="text" value="" name="fax">
        </div>
        <div class="userForm__field">
            <label class="userForm__label">Мобильный</label>
            <input class="userForm__text" type="text" value="" name="mobile">
        </div>
    </fieldset>
    <fieldset class="group address">
        <legend>Почтовый адрес</legend>
        <div class="userForm__field">
            <label class="userForm__label">Область / край:</label>
            <input class="userForm__text" type="text" value="" name="state">
        </div>
        <div class="userForm__field">
            <label class="userForm__label">Город:</label>
            <input class="userForm__text" type="text" value="" name="city">
        </div>
        <div class="userForm__field">
            <label class="userForm__label">Почтовый индекс:</label>
            <input class="userForm__text" type="text" value="" name="zip">
        </div>
    </fieldset>
</form>
<div class="resultCount" id="resultCount"></div>
<button id="findFormElements">Подсчитать у всей формы</button>
<button id="findFormElements-phones">Подсчитать у блока "Телефоны"</button>
.userForm {
    display: grid;
    grid-gap: 20px;
    grid-template-columns: 1fr 1fr 1fr;
}

.userForm__descr {
    margin-bottom: 20px;
    color: #888888;
}

.userForm__field {
    margin-bottom: 20px;
}

.userForm__label {
    display: block;
}

.userForm__text {
    width: 100%;
}

.userForm__text:focus {
    border: 2px solid #2363cf;
}

.resultCount {
    padding: 15px 0;
}

fieldset.group {
    border-color: #e7e7e7;
    border-width: 1px;
    border-style: solid;
    -o-border-image: none;
    border-image: none;
    border-radius: 6px;
}

fieldset.group legend {
    font-weight: 700;
    padding: 0 20px;
}

.addFocus {
    border-radius: 3px;
    color: #0173C1;
    cursor: pointer;
    text-decoration: underline;
}
Скачать
Исходные файлы BX.findFormElements

BX.getCaretPosition / BX.setCaretPosition

Функции для установки курсора в текстовом поле textobject на заданную позицию, а также получении текущей позиции курсора из текстового поля textobject 

BX.ready(function () {
    BX.bindDelegate(document.body, 'click', {
        tagName: 'button'
    }, function () {
        // Получаем id кнопки
        const nameId = this.getAttribute("id");
        // Место для вставки с результатами
        const text = document.getElementById("resultPos");

        // Функция вставки результата
        function setContent(object, content) {
            object.innerHTML = " ";
            object.insertAdjacentHTML("beforeend", content);
        }

        // Кнопка "Получить позицию"
        if (nameId === "getCaretPosition") {
            const getPos = BX.getCaretPosition(BX("text"));
            BX.setCaretPosition(BX("text"), getPos);
            setContent(text, "Позиция курсора - " + getPos)
        }
        // Кнопка "Установить позицию"
        if (nameId === "setCaretPosition") {
            const count = document.getElementById("text").value.length;
            const getPos = document.getElementById("setPos");
            if ((getPos.value) > count) {
                setContent(text, "Упс! Макс позиция  - " + count);
            } else {
                if (getPos.value > 0) {
                    BX.setCaretPosition(BX("text"), getPos.value);
                    setContent(text, "Позиция курсора - " + getPos.value);
                } else {
                    setContent(text, "Укажите позицию больше \"0\"");
                }
            }
        }
    })
})
<textarea class="cursorPos" id="text" rows="4">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab asperiores aspernatur assumenda commodi dolorem dolorum eligendi error excepturi exercitationem, impedit inventore magni obcaecati recusandae rerum tempora. Beatae earum magni quisquam!</textarea>
<div class="resultPos" id="resultPos"></div>
<button id="getCaretPosition">Получить позицию</button>
<input type="number" value="" id="setPos">
<button id="setCaretPosition">Установить позицию</button>
textarea.cursorPos {
    width: 100%;
    border-radius: 2px;
    padding: 10px 20px;
}

textarea.cursorPos:focus {
    border-color: #5d5fd0;
    outline: 0;
    -webkit-box-shadow: 0 0 0 0.2rem #4870cf;
    box-shadow: 0 0 0 0.2rem #4870cf;
}

.resultPos {
    padding: 10px 0;
}

b.error {
    color: #ee3232;
}
Скачать
Исходные файлы BX.getCaretPosition / BX.setCaretPosition

BX.setUnselectable/BX.setSelectable

Функции выключают / включают возможность пользовательского выделения внутри передаваемого элемента.
BX.ready(function () {
    // Разрешаем выделение
    BX.bindDelegate(
        document.body, 'click', {className: 'setSelectable'},
        function () {
            BX.setSelectable(BX("text"));
            BX.removeClass(BX("text"), "disabled");
        }
    )
    // Запрещаем выделение
    BX.bindDelegate(
        document.body, 'click', {className: 'setUnselectable'},
        function () {
            BX.setUnselectable(BX("text"));
            BX.addClass(BX("text"), "disabled");
        }
    )
})
<div class="demo-text" id="text">
  <h2>Выделение текста мышкой</h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur atque blanditiis, consectetur corporis delectus, magni nesciunt obcaecati odit omnis pariatur possimus qui quo reiciendis sapiente suscipit totam, ut vel velit!</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Corporis hic id ipsa magnam natus nesciunt quidem saepe sit soluta. Alias cupiditate illum officia, omnis quaerat sed sunt ut! Neque, placeat!</p>
</div>
<div class="btns">
  <button class="setSelectable btn">Разрешить</button>
  <button class="setUnselectable btn">Запретить</button>
</div>
.demo-text h2 {
    margin-bottom: 10px;
    font-size: 16px;
}

.demo-text p {
    color: #888888;
    margin-bottom: 15px;
}

.demo-text p:last-child {
    margin-bottom: 0;
}

.demo-text.disabled {
    cursor: no-drop;
}

.btns {
    margin-top: 20px;
}

button.btn {
    border: none;
    color: #fff;
    cursor: pointer;
    padding: 10px 20px;
    border-radius: 3px;
}

.setSelectable {
    background: #1aca1a;
}

.setUnselectable {
    background: #ee3232;
}
Скачать
Исходные файлы BX.setUnselectable/BX.setSelectable

BX.remove

Функция удаляет узел DOM-структуры.

Расcмотрим на примере на котором показывал функцию "BX.create" и доработаем её добавив функционал удаления товара.

BX.ready(function () {
    // добавление товара
    BX.bindDelegate(document.body, 'click', {
        className: 'addItem'
    }, function () {
        // создаем товар
        var newItem = BX.create({
            tag: 'div',
            props: {
                className: 'products__item'
            },
            children: [BX.create({
                tag: 'div',
                props: {
                    className: 'products__name'
                },
                text: 'Кросовки'
            }), BX.create({
                tag: 'div',
                props: {
                    className: 'products__picture'
                },
                children: [BX.create({
                    tag: 'img',
                    props: {
                        className: 'products__name',
                        src: 'static/images/content/bx-remove/product.jpg',
                        alt: 'Кросовки'
                    }
                })]
            }), BX.create({
                tag: 'div',
                props: {
                    className: 'products__price'
                },
                text: '9 900 руб'
            }), BX.create({
                tag: 'button',
                props: {
                    className: 'products__remove'
                },
                html: '× удалить товар'
            })]
        }); // указываем куда вставить созданный товар

        var item = document.querySelector('.addItem'); // добавляем на страницу

        item.before(newItem);
    });
    // удаление товара
    BX.bindDelegate(document.body, 'click', {
        className: 'products__remove'
    }, function () {
        var item = BX.findParent(this, {
            "tag": "div",
            "class": "products__item"
        }, true);
        BX.remove(item);
        console.log(item);
    });
});
<div class="products">
    <div class="products__list">
        <div class="products__item">
            <div class="products__name">Кросовки</div>
            <div class="products__picture">
                <img src="static/images/content/bx-remove/product.jpg" alt="Кросовки">
            </div>
            <div class="products__price">9 900 руб</div>
            <button class="products__remove">× удалить товар</button>
        </div>
        <div class="products__item">
            <div class="products__name">Кросовки</div>
            <div class="products__picture">
                <img src="static/images/content/bx-remove/product.jpg" alt="Кросовки">
            </div>
            <div class="products__price">9 900 руб</div>
            <button class="products__remove">× удалить товар</button>
        </div>
        <div class="products__item addItem">
            <div class="products__name">+ Добавить товар</div>
        </div>
    </div>
</div>
.products {
    margin: 30px 0;
}

.products__list {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-gap: 20px;
}

.products__item {
    text-align: center;
    border-radius: 3px;
    border: 1px solid #EAEAEA;
    padding: 10px 20px;
}

.products__item.addItem {
    border: 4px dashed #EAEAEA;
    place-self: center;
    cursor: pointer;
    -webkit-transition: .3s all;
    -o-transition: .3s all;
    transition: .3s all;
}

.products__item.addItem:hover {
    border-color: #0173C1;
}

.products__price {
    font-weight: 700;
}

.products__remove {
    background: red;
    border: none;
    padding: 10px 20px;
    margin: 10px auto;
    color: #fff;
    border-radius: 3px;
    cursor: pointer;
}
Скачать
Исходные файлы BX.remove

BX.addClass/BX.removeClass

Функция добавляет/удаляет узлу node CSS-класс className.
BX.ready(function () {
  const btn = document.querySelector(".circle");

  // устанавливаем обработчик
  BX.bindDelegate(document.body, 'click', {
      className: 'addClass'
  }, function () {

      // предварительно очистим ранее добавленные классы
      BX.removeClass(btn, "green");
      BX.removeClass(btn, "red");
      BX.removeClass(btn, "yellow");

      // добавим выбранный класс
      BX.addClass(btn, this.dataset.color);
  });
});
<div class="circle"></div>
<div class="btns">
  <button class="addClass red" data-color="red">Красный</button>
  <button class="addClass yellow" data-color="yellow">Желтый</button>
  <button class="addClass green" data-color="green">Зеленый</button>
</div>
.circle {
    border-radius: 50%;
    width: 150px;
    height: 150px;
    margin: 30px 0;
    background: #EAEAEA;
    -webkit-transition: .3s all;
    -o-transition: .3s all;
    transition: .3s all;
}

.circle.red {
    background: #ee3232;
}

.circle.yellow {
    background: #f3f340;
}

.circle.green {
    background: #1aca1a;
}

button {
    color: #ffffff;
    border: none;
    border-radius: 3px;
    cursor: pointer;
    padding: 10px 20px;
}

button.red {
    background: #ee3232;
}

button.yellow {
    background: #f3f340;
    color: #2b2b32;
}

button.green {
    background: #1aca1a;
}
Скачать
Исходные файлы BX.addClass/BX.removeClass

BX.width/BX.height

Возвращает (или задает) ширину, высоту элемента DOM. Первым параметром передаётся элемент DOM. Если не передавать второй параметр (целое число), то вернется значение ширины или высоты. Если передать - значение задается.

В данном примере мы будем возвращать ширину и высоту элемента DOM.

BX.ready(function(){
    const blocks = document.querySelectorAll(".width-item");
    BX.bindDelegate(document.body, 'click', {
        className: 'btn-showSize'
    }, function () {
        // пробегаемся по всем блокам
        blocks.forEach(function(item) {
            // ищем нужный блок по классу для определении ширины и высоты
            const block = BX.findChild(item, {
                "tag": "div",
                "class": "width-block"
            }, true);

            // ищем нужный блок по классу для вставки ширины
            const width = BX.findChild(item, {
                "tag": "span",
                "class": "res-width"
            }, true);

            // ищем нужный блок по классу для вставки ширины
            const height = BX.findChild(item, {
                "tag": "span",
                "class": "res-height"
            }, true);

            // предварительно очистим
            width.innerHTML = " ";
            height.innerHTML = " ";

            // Применяем функцию и добавляем результат
            width.insertAdjacentHTML("beforeend", "Ширина - " + BX.width(block));
            height.insertAdjacentHTML("beforeend", "Высота - " + BX.height(block));
        });
    })
})
<div class="demo-width">
    <div class="width-item">
        <div class="width-block"></div>
        <div class="width-result">
            <span class="res-width"></span>
            <span class="res-height"></span>
        </div>
    </div>
    <div class="width-item">
        <div class="width-block"></div>
        <div class="width-result">
            <span class="res-width"></span>
            <span class="res-height"></span>
        </div>
    </div>
    <div class="width-item">
        <div class="width-block"></div>
        <div class="width-result">
            <span class="res-width"></span>
            <span class="res-height"></span>
        </div>
    </div>
</div>
.demo-width {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-gap: 30px;
}

.width-block {
    background: #0173C1;
}

.width-item:nth-child(1) .width-block {
    height: 133px;
}

.width-item:nth-child(2) .width-block {
    height: 99px;
}

.width-item:nth-child(3) .width-block {
    height: 40px;
}

.width-result span {
    display: block;
}

.btn-showSize {
    margin: 15px auto 0 auto;
    display: block;
}
Скачать
Исходные файлы BX.width/BX.height

BX.toggleClass

Функция переключает наличие/отсутствие CSS-класса className у узла node или производит ротацию CSS-классов, если className – массив.
BX.ready(function () {
    var body = document.querySelector("body")
    var btn = document.querySelector(".switch")
    
    BX.bindDelegate(
        document.body, 'click', {className: 'switch__label'},
        function () {
            BX.toggleClass(body, 'switch-bg');
            BX.toggleClass(btn, 'switch-border');
        }
    )
})
<div class="switch">
    <input type="checkbox" id="switch__checkbox">
    <label class="switch__label" for="switch__checkbox">
        <span class="switch__circle"></span>
    </label>
</div>
.switch-bg {
    background: #0b1821;
}

.switch-border {
    border: #0a2c42 solid 7px !important;
}

body {
    -webkit-transition: 1s;
    -o-transition: 1s;
    transition: 1s;
    z-index: 10;
}

#switch__checkbox {
    z-index: -10;
    position: absolute;
    left: 0;
    top: 0;
    display: none;
}

.switch {
    z-index: 99;
    position: absolute;
    overflow: hidden;
    width: 190px;
    height: 80px;
    left: 50%;
    top: 50%;
    border: 7px solid #c3b912;
    border-radius: 45px;
    margin-left: -95px;
    margin-top: -40px;
}

.switch__label {
    overflow: hidden;
    z-index: 10;
    position: absolute;
    width: 100%;
    height: 100%;
}

.switch__circle {
    position: absolute;
    z-index: 10;
    width: 49px;
    height: 49px;
    background: #d9d726;
    border-radius: 50%;
    top: 0;
    left: 0;
    margin-left: 10px;
    margin-top: 9px;
    -webkit-transition: all 1s;
    -o-transition: all 1s;
    transition: all 1s;
}

#switch__checkbox:not(checked) ~ .switch__label .switch__circle {
    -webkit-animation: size-back 0.625s linear;
    animation: size-back 0.625s linear;
    -moz-animation: size-back 0.625s linear both;
}

#switch__checkbox:checked ~ .switch__label .switch__circle {
    -webkit-transform: translateX(107px);
    -ms-transform: translateX(107px);
    transform: translateX(107px);
    -moz-transform: translateX(107px);
    background: #fff;
    -webkit-animation: size 0.625s linear;
    animation: size 0.625s linear;
    -moz-animation: size 0.625s linear;
}

.switch__circle:before {
    position: absolute;
    z-index: -10;
    content: '';
    width: 49px;
    height: 49px;
    top: 0;
    left: -50px;
    background: #eff3e4;
    border-radius: 50%;
    -webkit-transition: all 1s;
    -o-transition: all 1s;
    transition: all 1s;
    -moz-transition: all 1s;
}

#switch__checkbox:checked ~ .switch__label .switch__circle:before {
    -webkit-transform: translate3d(65%, 0, 0);
    transform: translate3d(65%, 0, 0);
    -moz-transform: translate3d(65%, 0, 0);
}

#switch__checkbox:checked ~ .switch__label .switch__circle:before {
    background: #0b1821;
}

@-webkit-keyframes size {
    0% {
        -webkit-transform: translateX(0) scale(1);
        transform: translateX(0) scale(1);
        background: #d9d726;
    }
    55% {
        -webkit-transform: translateX(45px) scale(0.5);
        transform: translateX(45px) scale(0.5);
        background: #d9d726;
    }
    100% {
        -webkit-transform: translateX(108px) scale(1);
        transform: translateX(108px) scale(1);
    }
}

@keyframes size {
    0% {
        -webkit-transform: translateX(0) scale(1);
        transform: translateX(0) scale(1);
        background: #d9d726;
    }
    55% {
        -webkit-transform: translateX(45px) scale(0.5);
        transform: translateX(45px) scale(0.5);
        background: #d9d726;
    }
    100% {
        -webkit-transform: translateX(108px) scale(1);
        transform: translateX(108px) scale(1);
    }
}

@-webkit-keyframes size-back {
    0% {
        -webkit-transform: translateX(108px) scale(1);
        transform: translateX(108px) scale(1);
        background: white;
    }
    55% {
        -webkit-transform: translateX(45px) scale(0.5);
        transform: translateX(45px) scale(0.5);
    }
    100% {
        -webkit-transform: translateX(0) scale(1);
        transform: translateX(0) scale(1);
    }
}

@keyframes size-back {
    0% {
        -webkit-transform: translateX(108px) scale(1);
        transform: translateX(108px) scale(1);
        background: white;
    }
    55% {
        -webkit-transform: translateX(45px) scale(0.5);
        transform: translateX(45px) scale(0.5);
    }
    100% {
        -webkit-transform: translateX(0) scale(1);
        transform: translateX(0) scale(1);
    }
}
Скачать
Исходные файлы BX.toggleClass

BX.setOpacity

Метод устанавливает уровень прозрачности элемента веб-страницы.
BX.ready(function () {
  var btn = document.querySelector(".resultOpacityDemo");
  BX.bindDelegate(document.body, 'change', {
    className: 'setOpacity-demo'
  }, function () {
    BX.setOpacity(btn, this.value / 100);
  });
});
<div class="resultOpacityDemo"></div>
<input class="setOpacity-demo" type="range" min="0" max="100" value="100">
.resultOpacityDemo {
    width: 100px;
    height: 100px;
    background: #0173C1;
}
Скачать
Исходные файлы BX.setOpacity

BX.focus

Устанавливает фокус на элементе.
BX.ready(function () {
  // устанавливаем обработчик
  BX.bindDelegate(document.body, 'click', {
    className: 'addFocus'
  }, function () {
    // Определяем инпут и устанавливаем на него focus
    var phone = document.querySelector("[name='phone']");
    BX.focus(phone);
  });
});
<form class="form">
	<div class="form__field">
	  <label class="form__label">Имя</label>
	  <input class="form__text" type="text" value="" name="name" autofocus="">
	</div>
	<div class="form__field">
	  <label class="form__label">Телефон</label>
	  <input class="form__text" type="text" value="" name="phone">
	</div>
	<div class="form__field">
	  <div class="addFocus">Установить фокус на поле "Телефон"</div>
	</div>
</form>
.form__field {
    margin-bottom: 20px;
}

.form__label {
    display: block;
}

.form__text:focus {
    border: 2px solid #2363cf;
}

.addFocus {
    border-radius: 3px;
    color: #0173C1;
    cursor: pointer;
    text-decoration: underline;
}
Скачать
Исходные файлы BX.focus

BX.adjust

Функция позволяет изменить свойства узла node.
BX.ready(function () {
    // деактивируем кнопку отправить
    var btn = document.querySelector(".form__submit");

    BX.adjust(btn, {
        props: {
            disabled: true
        }
    });

    // устанавливаем обработчик на отслеживание введенных данных
    BX.bindDelegate(document.body, 'keyup', {
        className: 'form__text'
    }, function () {
        var inputName = document.querySelector("[name='name']");
        inputName = inputName.value.length;
        var inputPhone = document.querySelector("[name='phone']");
        inputPhone = inputPhone.value.length; // Проверка на кол-во символов

        if (inputName && inputPhone >= 5) {
            BX.adjust(btn, {
                props: {
                    disabled: false
                }
            });
        } else {
            BX.adjust(btn, {
                props: {
                    disabled: true
                }
            });
        }
    });
});
<form class="form">
    <div class="form__field">
        <label class="form__label">Имя</label>
        <input class="form__text" type="text" value="" name="name">
    </div>
    <div class="form__field">
        <label class="form__label">Телефон</label>
        <input class="form__text" type="text" value="" name="phone">
    </div>
    <div class="form__field">
        <input class="form__submit" type="submit" value="Отправить">
    </div>
</form>
.form__field {
    margin-bottom: 20px;
}

.form__label {
    display: block;
}

p {
    padding: 30px 0;
}
Скачать
Исходные файлы BX.adjust

BX.create

Создание узла DOM-структуры. Допускает при создании узла "подвеску" на него каких-то событий.
BX.ready(function () {
    // устанавливаем обработчик
    BX.bindDelegate(
        document.body, 'click', {className: 'addItem'},
        function () {
            // создаем товар
            var newItem = BX.create({
                tag: 'div',
                props: {className: 'products__item'},
                children: [
                    BX.create({
                        tag: 'div',
                        props: {
                            className: 'products__name'
                        },
                        text: 'Кросовки'
                    }),
                    BX.create({
                        tag: 'div',
                        props: {
                            className: 'products__picture'
                        },
                        children: [
                            BX.create({
                                tag: 'img',
                                props: {
                                    className: 'products__name',
                                    src: 'static/images/content/product.jpg',
                                    alt: 'Кросовки'
                                },
                            }),
                        ]
                    }),
                    BX.create({
                        tag: 'div',
                        props: {
                            className: 'products__price'
                        },
                        text: '9 900 руб'
                    }),
                ]
            });

            // указываем куда вставить созданный товар
            var item = document.querySelector('.addItem');

            // добавляем на страницу
            item.before(newItem);
        }
    );
})
<div class="products">
  <div class="products__list">
    <div class="products__item">
      <div class="products__name">Кросовки</div>
      <div class="products__picture"><img src="static/images/content/product.jpg" alt="Кросовки"></div>
      <div class="products__price">9 900 руб</div>
    </div>
    <div class="products__item">
      <div class="products__name">Кросовки</div>
      <div class="products__picture"><img src="static/images/content/product.jpg" alt="Кросовки"></div>
      <div class="products__price">9 900 руб</div>
    </div>
    <div class="products__item addItem">
      <div class="products__name">+ Добавить</div>
    </div>
  </div>
</div>
.products {
    margin: 30px 0;
}

.products__list {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-gap: 20px;
}

.products__item {
    text-align: center;
    border-radius: 3px;
    border: 1px solid #EAEAEA;
    padding: 10px 20px;
}

.products__item.addItem {
    border: 4px dashed #EAEAEA;
    place-self: center;
    cursor: pointer;
    -webkit-transition: .3s all;
    -o-transition: .3s all;
    transition: .3s all;
}

.products__item.addItem:hover {
    border-color: #0173C1;
}

.products__price {
    font-weight: 700;
}
Скачать
Исходные файлы BX.create
Возврат к списку