grayscale(), sepia(), saturate() и hue-rotate() меняют цветовую палитру элемента без редактора. У grayscale() и sepia() пустые скобки значат не "без изменений", а сразу 100% эффекта - это часто удивляет новичков. У saturate() в отличие от них нет потолка в 100%. А hue-rotate() - единственная функция фильтра, которая разрешает отрицательные значения.
В этом уроке
Попробуй прямо сейчас: у карточки написано filter: grayscale(); - совсем без числа и без %. Это НЕ значит "без изменений": пустые скобки у grayscale() означают 100%, поэтому карточка полностью чёрно-белая. Поменяй на grayscale(50%), чтобы увидеть частичный эффект - половину цвета вернёшь обратно.
grayscale() и sepia(): проценты с потолком в 100%
У grayscale() и sepia() одинаковый синтаксис: число или процент, 0%/0 - без изменений, 100%/1 - максимальный эффект (полностью чёрно-белое или полностью сепия). Если указать значение ВЫШЕ 100%, оно просто ОБРЕЗАЕТСЯ до 100% - собственная проверка это подтвердила: grayscale(150%) вычисляется как ровно grayscale(1), а не как что-то "более чёрно-белое". У обеих функций есть неочевидная особенность: если СОВСЕМ не указать аргумент (пустые скобки), это значит не "без изменений", а РОВНО НАОБОРОТ - 100%, максимальный эффект. Так прямо написано в документации MDN, и собственная проверка это подтвердила: grayscale() и grayscale(100%) дают одинаковый результат.
.photo {
filter: grayscale(60%);
} - явный процент, частичное обесцвечивание.
Пустые скобки - не "без эффекта", а максимум:
.photo {
filter: grayscale();
}
/* ожидание: "аргумент не указан - значит эффекта нет" */ - на деле это 100%, карточка полностью чёрно-белая, а не цветная.
saturate() и hue-rotate(): без потолка - и отрицательные значения
saturate() тоже принимает число или процент (100%/1 по умолчанию - без изменений, 0 - полностью обесцвечено), но в отличие от grayscale() и sepia() у неё НЕТ потолка в 100% - значения выше реально усиливают насыщенность. Проверено: saturate(150%) вычисляется именно как saturate(1.5), без обрезания. Кстати, saturate(0) и grayscale(100%) на одном и том же цвете дают численно одинаковый результат пикселя - для полного обесцвечивания без разницы, какую функцию использовать.
hue-rotate() устроена совсем иначе - она принимает угол (deg), а не проценты, 0deg по умолчанию - без изменений. И это ЕДИНСТВЕННАЯ функция фильтра, которая разрешает ОТРИЦАТЕЛЬНЫЕ значения: у blur, brightness, contrast, grayscale, sepia и saturate отрицательные числа всегда делают всю запись filter невалидной, а у hue-rotate(-90deg) - работает без проблем, просто вращает цветовой круг в другую сторону. Проверено даже численно: hue-rotate(-90deg) и hue-rotate(270deg) дают одинаковый результат - это буквально вращение по кругу, а не ограниченная величина.
.icon {
filter: hue-rotate(-45deg);
} - отрицательный угол валиден, просто вращает в другую сторону.
А вот отрицательное значение у любой другой функции фильтра ломает запись:
.icon {
filter: saturate(-20%);
} - у saturate(), как и у blur/brightness/contrast/grayscale/sepia, отрицательные значения запрещены - вся запись filter станет невалидной.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Думать, что grayscale() или sepia() без аргумента значит "без изменений" | Пустые скобки означают 100% - максимальный эффект, а не отсутствие эффекта | Для "без эффекта" писать явный 0% - grayscale(0%) |
| Указывать grayscale(150%) или sepia(150%), ожидая усиления эффекта сверх 100% | Значения выше 100% просто обрезаются до 100%, сильнее эффект не станет | Для более выраженного эффекта комбинировать с contrast() или saturate(), а не превышать 100% |
| Считать, что у всех функций фильтра отрицательные значения запрещены одинаково | hue-rotate() - исключение: отрицательные углы полностью валидны и просто вращают в другую сторону | Смело использовать отрицательные градусы у hue-rotate, но не у остальных функций фильтра |
| Не глядя приравнивать эффект saturate() к grayscale() по названию | При saturate(0) результат численно совпадает с grayscale(100%) на том же цвете, хотя названия разные | Использовать любую из двух для полного обесцвечивания - разница только в записи |
Шпаргалка
| Запись | Что означает |
|---|---|
| grayscale() / grayscale(100%) | Полностью чёрно-белое (пустые скобки = 100%, не "без изменений") |
| grayscale(0%) (по умолчанию при явном указании) | Без изменений |
| grayscale(150%) | Обрежется до 100%, сильнее не станет |
| saturate(0) | Полностью обесцвечено (совпадает с grayscale(100%)) |
| saturate(150%) | Реально усиливает насыщенность, потолка нет |
| hue-rotate(90deg) | Поворот цветового круга на 90° |
| hue-rotate(-90deg) | Валидно! Единственная функция фильтра, разрешающая отрицательные значения |
Коротко: отвечаем на вопросы
Можно ли перекрасить чёрную SVG-иконку в произвольный цвет одним только CSS?
Да, это реальный приём (описан на Хабре, qna.habr.com/q/600778): для перекраски чёрной или белой SVG-иконки в конкретный нужный цвет используют КОМБИНАЦИЮ из нескольких filter-функций сразу - invert, sepia, saturate, hue-rotate, brightness и contrast, подобранных так, чтобы итоговый цвет совпал с нужным. Один только hue-rotate() сдвигает оттенок у УЖЕ цветной картинки, а для превращения чёрного/белого в произвольный цвет нужна вся комбинация - invert, brightness и contrast разбираются в других уроках курса.
Если написать просто filter: grayscale(); совсем без числа - это значит "без эффекта"?
Нет, ровно наоборот: у grayscale() (и у sepia()) пустые скобки означают 100% - максимальный эффект, а не "без изменений". Это подтверждено официальной документацией MDN и собственной проверкой: grayscale() и grayscale(100%) дают одинаковый результат. Для "без эффекта" нужно явно писать 0% - grayscale(0%).