blur(), brightness() и contrast() - три самые практичные функции CSS-фильтров. blur() принимает только длину в пикселях (не проценты) и размывает элемент вместе с его собственным краем. brightness() и contrast() принимают число или процент: 100%/1 - без изменений, 0 - крайность (чёрный или серый), а забытый знак % превращает мягкую поправку в почти ослепительный эффект.
В этом уроке
Попробуй прямо сейчас: карточка размыта и затемнена, пока курсор не наведён - filter: blur(6px) brightness(0.6). При наведении оба значения меняются на blur(0) brightness(1) (то есть "без изменений"), и transition: filter плавно анимирует переход между двумя состояниями фильтра - тот же приём, что уже разбирался на transition и :hover.
blur(): размытие в пикселях, не в процентах
blur() - единственная из этих трёх функций, которая принимает ТОЛЬКО длину (px, em, rem и так далее), проценты для неё недопустимы. Число без единицы измерения тоже невалидно - с одним исключением: голый 0 (без px) допустим, как и для большинства CSS-длин. Собственная проверка это подтвердила: blur(0) браузер принял как валидный blur(0px), а вот blur(5) без единицы - НЕТ, и это сломало не только саму функцию blur, а ВЕСЬ filter целиком: вычисленное значение стало none, то есть эффект пропал полностью, даже если рядом в списке стояли другие правильные функции. Отрицательные значения (blur(-5px)) тоже запрещены и ломают запись точно так же.
.card {
filter: blur(6px) contrast(1.2);
} - у blur указана единица px, вся запись валидна, работают обе функции.
Забытая единица измерения ломает всё, а не только blur:
.card {
filter: blur(6) contrast(1.2);
} - blur(6) без px делает невалидной ВСЮ запись filter, даже полностью правильный contrast(1.2) рядом перестаёт работать.
brightness() и contrast(): проценты или числа - и опасная опечатка
У brightness() и contrast() синтаксис одинаковый и отличается от blur(): они принимают ЧИСЛО или ПРОЦЕНТ, обе формы взаимозаменяемы - brightness(1) и brightness(100%) значат одно и то же, как и brightness(0.4) и brightness(40%). У обеих 100%/1 (по умолчанию) означает "без изменений". У brightness() 0%/0 даёт полностью чёрный результат, у contrast() 0%/0 - полностью серый (контраст пропадает). Значения выше 100% разрешены и усиливают эффект - ярче или контрастнее исходного.
Здесь прячется по-настоящему опасная опечатка: если забыть знак % и написать голое число, думая, что "150" значит "150%", получится совсем не то. Число 1 равно 100%, значит число 150 равно 15000% - в сто раз сильнее, чем скорее всего имелось в виду. Собственная проверка на конкретном цвете это подтвердила: brightness(150) дал ПОЛНОСТЬЮ БЕЛЫЙ, пересвеченный результат, тогда как правильная запись brightness(1.5) (то же самое, что brightness(150%)) для того же цвета дала мягкое, ожидаемое посветление.
.photo {
filter: brightness(1.5);
} - число 1.5 = 150%, мягкое осветление.
Забытый знак % превращает мягкую поправку в почти ослепительный эффект:
.photo {
filter: brightness(150);
} - число 150 = 15000% (не 150%!), результат почти полностью белый, а не мягко светлее.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Писать blur(5) без единицы измерения | Вся запись filter становится невалидной целиком, а не только сама функция blur | Всегда указывать единицу длины у blur (px, em и т.д.), кроме особого случая blur(0) |
| Забыть знак % у brightness/contrast, написав голое число вроде 150 | 150 без % равно 15000%, а не 150% - результат в сто раз сильнее ожидаемого | Писать явный процент (150%) или дробное число (1.5), а не голое целое число больше 1 |
| Указывать отрицательные значения (blur(-5px), brightness(-1)) | Отрицательные значения запрещены спецификацией, вся запись filter становится невалидной | Использовать другие функции для нужного эффекта (например invert() - тема следующего урока), а не отрицательные числа |
| Менять только одну функцию в длинном списке filter, не проверяя остальные | Если новое значение окажется невалидным, сломается ВЕСЬ filter, а не только изменённая функция | После правки проверять результат визуально - невалидная функция где угодно в списке гасит всё |
Шпаргалка
| Запись | Что означает |
|---|---|
| blur(6px) | Только длина, проценты недопустимы; blur(0) - особый случай, валиден без единицы |
| brightness(1) / brightness(100%) (по умолчанию) | Без изменений |
| brightness(0) / brightness(0%) | Полностью чёрный |
| contrast(1) / contrast(100%) (по умолчанию) | Без изменений |
| contrast(0) / contrast(0%) | Полностью серый |
| Значение больше 1 / больше 100% | Разрешено, усиливает эффект |
| Одна невалидная функция в списке filter | Ломает весь filter целиком |
Коротко: отвечаем на вопросы
Почему у размытого блока светлеют/бледнеют края, хотя внутри цвет однородный?
Потому что blur() размывает элемент вместе с его собственной границей - у самого края в размытие подмешивается то, что находится СНАРУЖИ (например фон страницы позади). Собственная проверка это подтвердила: сплошной красный блок на белом фоне с сильным blur() остался чистым красным только в центре, а у самой границы заметно побледнел, потому что размытие «зачерпнуло» белый фон снаружи. Эту же проблему реально описывали на Хабре (qna.habr.com/q/412623). Практический выход - делать размытый элемент заметно больше видимой области и обрезать выцветшую кайму через overflow: hidden на контейнере.
Правда ли, что blur() сильно нагружает браузер, в отличие от других фильтров?
Да, это один из самых "тяжёлых" filter-эффектов - на Хабре (qna.habr.com/q/539564) отмечали, что именно с blur всё "намного печальнее", чем с более лёгкими эффектами вроде обычных теней. Для одной статичной картинки разница незаметна, но если размытие анимировать или применять сразу к десяткам элементов, браузеру придётся пересчитывать эффект на каждом кадре - подробный разбор производительности будет в отдельном уроке курса.