Формошлёп
3.93K subscribers
200 photos
151 videos
247 links
Шлёпаем формы и красим кнопки...

Блог про фронтенд — просто, понятно и с юмором. Всех обнял, приподнял, пошел пилить для вас годноту)

Связь: @advertos
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
Перемещаем выбранный тег в начало списка без JS

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

Ключ к этому эффекту — свойство order внутри Flexbox-контейнера, но давайте по порядку)

HTML:
<label class="tag">
<input type="checkbox">
HTML5/CSS3
</label>
<label class="tag">
<input type="checkbox">
JavaScript
</label>

Чекбокс спрятан внутри <label>, что позволяет кликать по всему тегу.

Скрываем чекбокс:
.tag input {
display: none;
}


Располагаем теги в ряд:
.tags-wrapper {
display: flex;
flex-wrap: wrap;
gap: 10px;
}


Динамическое изменение порядка:
.tag:has(:checked) {
background: #007bff;
color: white;
order: -1;
}

Селектор :has(:checked) определяет, отмечен ли чекбокс внутри тега. Свойство order: -1 перемещает элемент в начало.

Так просто с помощью :has() и Flexbox мы получаем крутой интерактивный интерфейс)

Пример кода здесь.
1🔥25👍16😐21
This media is not supported in your browser
VIEW IN TELEGRAM
Анимация ::marker в списке

Нашел интересный способ анимации маркеров списка. Разберем, как сделать, чтобы при наведении на элемент списка плавно появлялся наш кастомный маркер.

HTML:
<ul>
<li>Первый</li>
<li>Второй</li>
<li>Третий</li>
<li>Четвертый</li>
<li>Пятый</li>
</ul>

Делаем обычный список.

CSS:
li::marker {
content: "🔥 ";
color: transparent;
transition: color 200ms;
}
li:hover::marker {
color: black;
}

content: "🔥 "; — ставим наш кастомный маркер.
color: transparent; — скрываем его, делая прозрачным.
transition: color 300ms; — обеспечиваем плавное появление.
color: black; — при ховере, меняем цвет и делаем маркер видимым.

Главная фишка: в контексте ::marker браузеры по умолчанию используют текстовый режим рендеринга emoji. Поэтому color: black сработает, и наш маркер будет виден, даже если сам emoji цветной)

Код можно посмотреть здесь.
👍19🔥74
Приводим логотипы к единому стилю

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

Всего две CSS-строки превращают разношёрстную коллекцию в стильную монохромную галерею:
filter: grayscale(100%);
mix-blend-mode: multiply;


filter: grayscale(100%) — преобразует изображение в чёрно-белое. Цветные логотипы становятся серыми, но фон остаётся.
mix-blend-mode: multiply — этот режим наложения работает по принципу умножения цветов. Белые области становятся прозрачными, а тёмные части логотипа остаются видимыми. Фон страницы просвечивает сквозь изображение.

Остается подогнать размеры:
.brands__item img {
width: 200px;
aspect-ratio: 2 / 1;
object-fit: contain;
}

aspect-ratio: 2 / 1; — задаёт пропорции 2:1.
object-fit: contain; — логотип вписывается в область без обрезки и искажений.

Идеально для секций "Наши клиенты" или "Партнёры")

Глянуть код можно тут.
2🔥35👍176👎1
This media is not supported in your browser
VIEW IN TELEGRAM
Анимированный гамбургер для меню

Давайте сегодня разберем, как сделать простую, но доступную и красивую кнопку для мобильного меню.

HTML:
<button type="button" class="hamburger" aria-label="Открыть меню" aria-expanded="false">
<span class="hamburger__line"></span>
<span class="hamburger__line"></span>
<span class="hamburger__line"></span>
</button>

Используем <button>, а не <div> для семантики. ARIA-атрибуты помогают скринридерам понять назначение кнопки.

Базовая стилизация:
.hamburger {
display: flex;
flex-direction: column;
gap: 6px;
background: transparent;
border: none;
}

.hamburger__line {
width: 28px;
height: 3px;
background: #000;
transition: transform 0.3s, opacity 0.2s;
}

Flexbox для вертикального выстраивания линий, плавные переходы для анимации.

Анимация:
.hamburger.active .hamburger__line:nth-child(1) {
transform: translateY(9px) rotate(45deg);
}
.hamburger.active .hamburger__line:nth-child(2) {
opacity: 0;
}
.hamburger.active .hamburger__line:nth-child(3) {
transform: translateY(-9px) rotate(-45deg);
}

Верхняя и нижняя линии поворачиваются, средняя исчезает.

JS:
const hamburger = document.querySelector('.hamburger');
let isOpen = false;

hamburger.addEventListener('click', () => {
isOpen = !isOpen;
hamburger.classList.toggle('active');
hamburger.setAttribute('aria-expanded', isOpen);
hamburger.setAttribute('aria-label', isOpen ? 'Закрыть меню' : 'Открыть меню');
});

Переключаем класс и обновляем ARIA для доступности.

В итоге получаем семантичный, доступный и красиво анимированный гамбургер)

Затестить код можно здесь.
👍16🔥113
Стилизация select option

Бывает необходимость добавить для select кастомные стили, чтобы он не выбивался из дизайна. Давайте разберем, как в целом это можно сделать.

HTML:
<div class="select">
<select name="slct" id="slct">
<option>-- Выберите вариант --</option>
<option value="1">Вариант 1</option>
<!-- остальные options -->
</select>
</div>

Обертываем select в div для дополнительного контроля над стилями.

Сбрасываем стандартные стили:
select {
appearance: none;
border: 0;
outline: 0;
background: transparent;
}


Создаем wrapper-контейнер:
.select {
position: relative;
overflow: hidden;
background: #2c3e50;
border-radius: 0.25em;
}


Он нужен для добавления кастомной стрелки, а overflow: hidden обрезает стандартную стрелку браузера.

Добавляем стрелку:
.select::after {
content: "▼";
position: absolute;
right: 0;
pointer-events: none; /* Клики проходят сквозь стрелку */
background: #34495e;
}

pointer-events: none позволяет кликать "сквозь" псевдоэлемент на сам селект.

Стилизуем select:
select {
width: 100%;
padding: 0 3em 0 1em; /* Отступ справа под стрелку */
cursor: pointer;
}

Правый padding (3em) освобождает место для нашей кастомной стрелки.

Стилизуем опции:
select option {
background-color: #2c3e50;
color: white;
}


В итоге wrapper + псевдоэлемент дают нам возможность кастомизировать select)

Пример кода, как всегда, здесь.
👍22🔥107
Shortcut-домены с .new

Если вы часто тестируете код в CodePen или CodeSandbox, создаете заметки в Google Документах или фиксируете данные в Google Таблицах, то для этого дела удобно использовать специальные домены .new.

.new — домен верхнего уровня для быстрого создания нового контента. По сути, это аналог комбинации Ctrl+N или меню "File → New" в офлайн-приложениях, но для веба.

Принцип простой: набираем короткий адрес, моментально попадаете в редактор или форму создания.

Для разработки:
pen.new → Пустой CodePen
js.new → JavaScript-окружение в CodeSandbox
react.new → React-проект в CodeSandbox
vue.new → Vue-проект в CodeSandbox
nodejs.new → Node.js-окружение в CodeSandbox

Документы Google:
docs.new → Новый Google Документ
sheets.new → Новая Google Таблица
slides.new → Новая Google Презентация

Полный список всех доступных сокращений можно найти здесь: whats.new/shortcuts

Маленькая, но приятная оптимизация, экономим секунды, которые за год складываются в часы чистого времени)
🔥16👍6😎6
Выглядит надёжно)
😁4411
Круговые диаграммы на чистом CSS

Если на странице нужно сверстать простенькую круговую диаграмму, то можно не спешить запиливать спец. библиотеки и т.п. Можно попробовать решить это с помощью conic-gradient().

conic-gradient() — CSS-функция, которая создаёт градиент, который вращается вокруг центральной точки (как циферблат часов).

Диаграмму на 30% / 40% / 30% можно нарисовать так:

Через градусы:
background: conic-gradient(
#ff6384 0deg 108deg, /* 30% = 108° */
#36a2eb 108deg 252deg, /* 40% = 144° */
#ffce56 252deg 360deg /* 30% = 108° */
);


Или проценты:
background: conic-gradient(
#ff6384 0% 30%,
#36a2eb 30% 70%,
#ffce56 70% 100%
);


Просто указываем диапазон для каждого цвета и все, получаем рабочую диаграмму)

Пример можно глянуть здесь.
1👍29🔥175
This media is not supported in your browser
VIEW IN TELEGRAM
Интерактивная кнопка поиска

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

HTML:
<div class="input-container">
<input type="search" required placeholder="Введите запрос">
<input type="submit" value="Поиск" class="search-btn">
</div>


Сделаем контейнер для инпута и кнопки:
.input-container {
display: flex;
align-items: center;
height: 2.5rem;
width: 100%;
max-width: 20rem;
background-color: #fff;
border-radius: 0.5rem;
padding: 0.35rem;
}

Теперь это выглядит, как одно целое.

Настраиваем состояния кнопки:
/* Исходное состояние - неактивная кнопка */
.search-btn {
background-color: gray;
opacity: 0.5;
pointer-events: none;
}

/* Активное состояние, когда в поле есть текст */
.input-container input[type="search"]:not(:placeholder-shown) + .search-btn {
background-color: #483D8B;
opacity: 1;
pointer-events: auto;
}

■ Изначально кнопка серая и неактивна.
:not(:placeholder-shown) срабатывает, когда placeholder не отображается (то есть в поле есть текст).
+ — соседний комбинатор, выбирает следующий элемент (нашу кнопку), меняет цвет, убирает прозрачность и включает кликабельность.

В результате получаем интерактивное поле поиска с автоматической активацией кнопки)

Код можно глянуть здесь.
👍14🔥113
Разделители между элементами списка

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

HTML:
<ul>
<li>Первый элемент</li>
<li>Второй элемент</li>
<li>Третий элемент</li>
<li>Четвертый элемент</li>
</ul>


CSS:
ul {
list-style-type: none;
padding: 0;
}

li {
font-size: 1.25rem;
padding: 1rem 0;
}

li:not(:last-of-type) {
border-bottom: 4px solid tomato;
}


■ Убираем маркеры списка и дефолтный левый отступ.
■ Указываем размер шрифта и отступы
■ Все li, кроме последнего получают нижнюю границу.

Еще можно было бы сделать так:
li {
border-bottom: 4px solid tomato;
}

li:last-child {
border-bottom: none;
}

Сначала добавляем границу всем, потом убираем у последнего.

Или через соседний селектор:
li + li {
border-top: 4px solid tomato;
}

+ выбирает элемент, идущий сразу после указанного. То есть "каждый li, перед которым есть другой li" получает границу сверху.

А можно и через Flexbox с gap:
ul {
display: flex;
flex-direction: column;
list-style-type: none;
padding: 0;
gap: 4px;
background: tomato;
}

li {
background: white;
padding: 1rem 0;
}

gap создает промежутки между flex-элементами. Цвет фона ul просвечивает через эти промежутки.

В общем есть из чего выбрать, но как по мне :not(:last-of-type) — самый читаемый вариант)

Все примеры можно посмотреть здесь.
🔥1872👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Стильный hover cards эффект

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

HTML:
<div class="card from-bottom">
<div class="front-content">Снизу ↑</div>
<div class="content">
<p class="heading">From Bottom</p>
<p>Описание скрытого контента...</p>
</div>
</div>

Здесь у нас двухслойная система: front-content (видимый слой) + content (скрытый контент).
Стилизуем карточки, как нам нужно.

Анимация:
/* Снизу → Вверх */
.card.from-bottom .content {
transform: translate(0, 96%);
}

.card.from-bottom:hover .content {
transform: translate(0, 0);
}

Скрываем контент на 96% за границу → Hover возвращает в ноль.

А пока content въезжает, front-content уезжает на 30% и исчезает:
.card.from-bottom:hover .front-content {
transform: translate(0, -30%);
}


Простое работающее решение, которое можно кастомизировать за секунды)

Пример кода с разными направлениями здесь.
🔥16👍112