Фильтры и blend modes дают CSS-фотошоп прямо в браузере: размытие, обесцвечивание, контраст, наложение слоёв. Без Canvas, без JS-библиотек.
/* Базовые функции */
.image {
filter: blur(4px); /* Размытие (Gaussian blur) */
filter: brightness(1.5); /* Яркость: >1 светлее, <1 темнее */
filter: contrast(2); /* Контраст: >1 больше, <1 меньше */
filter: grayscale(1); /* 0 = цвет, 1 = ч/б */
filter: saturate(0.5); /* 0 = серый, 1 = норма, 2 = насыщенный */
filter: hue-rotate(90deg); /* Сдвиг цветового тона */
filter: invert(1); /* Инверсия цветов */
filter: sepia(0.8); /* Сепия */
filter: opacity(0.5); /* Прозрачность (как opacity, но compositing) */
}
/* drop-shadow — тень повторяет форму (в отличие от box-shadow) */
.icon {
filter: drop-shadow(4px 4px 8px rgba(0,0,0,0.4));
}
/* Комбинирование — применяются слева направо */
.stylized {
filter: contrast(1.2) brightness(1.1) saturate(1.3);
}Применяется к содержимому ЗА элементом (не к самому элементу):
/* Glassmorphism — стеклянный эффект */
.glass-card {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(12px) saturate(1.8);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 16px;
}
/* Затемнённый модальный фон */
.modal-overlay {
backdrop-filter: blur(4px) brightness(0.7);
}.text-overlay {
mix-blend-mode: multiply; /* Умножение — тёмные тона */
mix-blend-mode: screen; /* Экран — светлые тона */
mix-blend-mode: overlay; /* Наложение — комбо */
mix-blend-mode: difference; /* Разница — инверсия */
mix-blend-mode: luminosity; /* Яркость */
mix-blend-mode: color; /* Цвет без яркости */
}
/* Классический эффект: текст "вырезает" фон */
.knockout-text {
mix-blend-mode: multiply;
color: black; /* На белом фоне станет прозрачным */
}/* Два фона с наложением */
.duotone {
background-image:
linear-gradient(to right, #7b2ff7, #06b6d4),
url(photo.jpg);
background-blend-mode: luminosity;
/* Даёт эффект двухцветной фотографии */
}Hover с desaturate:
.portfolio-item {
filter: grayscale(1) brightness(0.8);
transition: filter 0.3s;
}
.portfolio-item:hover {
filter: grayscale(0) brightness(1);
}Неоновое свечение через drop-shadow:
.neon-text {
filter:
drop-shadow(0 0 8px #7b2ff7)
drop-shadow(0 0 20px #7b2ff7)
drop-shadow(0 0 40px #7b2ff7);
}Матовое стекло:
.frosted {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px); /* Safari */
}filter и backdrop-filter создают stacking context и новый composite layer. blur() — одна из дорогих операций; для производительности ограничивай радиус и площадь элемента.
Интерактивный редактор CSS-фильтров с ползунками для каждого параметра
// CSS фильтры — интерактивный редактор
const style = document.createElement('style')
style.textContent = `
body { font-family: sans-serif; padding: 16px; }
.editor { display: flex; gap: 16px; flex-wrap: wrap; }
.target {
width: 200px; height: 150px;
background: linear-gradient(135deg, #7b2ff7 0%, #06b6d4 50%, #f59e0b 100%);
border-radius: 12px;
flex-shrink: 0;
transition: filter 0.2s;
}
.controls { flex: 1; min-width: 220px; }
.control-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.control-row label { width: 110px; font-size: 13px; }
.control-row input { flex: 1; }
.control-row span { width: 40px; font-size: 12px; text-align: right; color: #7b2ff7; }
pre { background: #1a202c; color: #a0aec0; padding: 8px; border-radius: 6px; font-size: 11px; margin-top: 8px; }
`
document.head.appendChild(style)
const editor = document.createElement('div')
editor.className = 'editor'
document.body.appendChild(editor)
const target = document.createElement('div')
target.className = 'target'
editor.appendChild(target)
const controlsDiv = document.createElement('div')
controlsDiv.className = 'controls'
editor.appendChild(controlsDiv)
const filterConfig = [
{ name: 'blur', unit: 'px', min: 0, max: 20, step: 0.5, default: 0 },
{ name: 'brightness', unit: '', min: 0, max: 3, step: 0.1, default: 1 },
{ name: 'contrast', unit: '', min: 0, max: 4, step: 0.1, default: 1 },
{ name: 'grayscale', unit: '', min: 0, max: 1, step: 0.05, default: 0 },
{ name: 'saturate', unit: '', min: 0, max: 4, step: 0.1, default: 1 },
{ name: 'hue-rotate', unit: 'deg', min: 0, max: 360, step: 5, default: 0 },
]
const values = {}
filterConfig.forEach(cfg => { values[cfg.name] = cfg.default })
const output = document.createElement('pre')
function updateFilter() {
const parts = filterConfig
.filter(c => values[c.name] !== c.default)
.map(c => `${c.name}(${values[c.name]}${c.unit})`)
const filterStr = parts.length ? parts.join(' ') : 'none'
target.style.filter = filterStr
output.textContent = `filter: ${filterStr};`
}
filterConfig.forEach(cfg => {
const row = document.createElement('div')
row.className = 'control-row'
const label = document.createElement('label')
label.textContent = cfg.name
const input = document.createElement('input')
input.type = 'range'
input.min = cfg.min
input.max = cfg.max
input.step = cfg.step
input.value = cfg.default
const span = document.createElement('span')
span.textContent = cfg.default + cfg.unit
input.addEventListener('input', () => {
values[cfg.name] = parseFloat(input.value)
span.textContent = input.value + cfg.unit
updateFilter()
})
row.appendChild(label)
row.appendChild(input)
row.appendChild(span)
controlsDiv.appendChild(row)
})
controlsDiv.appendChild(output)
updateFilter()Фильтры и blend modes дают CSS-фотошоп прямо в браузере: размытие, обесцвечивание, контраст, наложение слоёв. Без Canvas, без JS-библиотек.
/* Базовые функции */
.image {
filter: blur(4px); /* Размытие (Gaussian blur) */
filter: brightness(1.5); /* Яркость: >1 светлее, <1 темнее */
filter: contrast(2); /* Контраст: >1 больше, <1 меньше */
filter: grayscale(1); /* 0 = цвет, 1 = ч/б */
filter: saturate(0.5); /* 0 = серый, 1 = норма, 2 = насыщенный */
filter: hue-rotate(90deg); /* Сдвиг цветового тона */
filter: invert(1); /* Инверсия цветов */
filter: sepia(0.8); /* Сепия */
filter: opacity(0.5); /* Прозрачность (как opacity, но compositing) */
}
/* drop-shadow — тень повторяет форму (в отличие от box-shadow) */
.icon {
filter: drop-shadow(4px 4px 8px rgba(0,0,0,0.4));
}
/* Комбинирование — применяются слева направо */
.stylized {
filter: contrast(1.2) brightness(1.1) saturate(1.3);
}Применяется к содержимому ЗА элементом (не к самому элементу):
/* Glassmorphism — стеклянный эффект */
.glass-card {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(12px) saturate(1.8);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 16px;
}
/* Затемнённый модальный фон */
.modal-overlay {
backdrop-filter: blur(4px) brightness(0.7);
}.text-overlay {
mix-blend-mode: multiply; /* Умножение — тёмные тона */
mix-blend-mode: screen; /* Экран — светлые тона */
mix-blend-mode: overlay; /* Наложение — комбо */
mix-blend-mode: difference; /* Разница — инверсия */
mix-blend-mode: luminosity; /* Яркость */
mix-blend-mode: color; /* Цвет без яркости */
}
/* Классический эффект: текст "вырезает" фон */
.knockout-text {
mix-blend-mode: multiply;
color: black; /* На белом фоне станет прозрачным */
}/* Два фона с наложением */
.duotone {
background-image:
linear-gradient(to right, #7b2ff7, #06b6d4),
url(photo.jpg);
background-blend-mode: luminosity;
/* Даёт эффект двухцветной фотографии */
}Hover с desaturate:
.portfolio-item {
filter: grayscale(1) brightness(0.8);
transition: filter 0.3s;
}
.portfolio-item:hover {
filter: grayscale(0) brightness(1);
}Неоновое свечение через drop-shadow:
.neon-text {
filter:
drop-shadow(0 0 8px #7b2ff7)
drop-shadow(0 0 20px #7b2ff7)
drop-shadow(0 0 40px #7b2ff7);
}Матовое стекло:
.frosted {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px); /* Safari */
}filter и backdrop-filter создают stacking context и новый composite layer. blur() — одна из дорогих операций; для производительности ограничивай радиус и площадь элемента.
Интерактивный редактор CSS-фильтров с ползунками для каждого параметра
// CSS фильтры — интерактивный редактор
const style = document.createElement('style')
style.textContent = `
body { font-family: sans-serif; padding: 16px; }
.editor { display: flex; gap: 16px; flex-wrap: wrap; }
.target {
width: 200px; height: 150px;
background: linear-gradient(135deg, #7b2ff7 0%, #06b6d4 50%, #f59e0b 100%);
border-radius: 12px;
flex-shrink: 0;
transition: filter 0.2s;
}
.controls { flex: 1; min-width: 220px; }
.control-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.control-row label { width: 110px; font-size: 13px; }
.control-row input { flex: 1; }
.control-row span { width: 40px; font-size: 12px; text-align: right; color: #7b2ff7; }
pre { background: #1a202c; color: #a0aec0; padding: 8px; border-radius: 6px; font-size: 11px; margin-top: 8px; }
`
document.head.appendChild(style)
const editor = document.createElement('div')
editor.className = 'editor'
document.body.appendChild(editor)
const target = document.createElement('div')
target.className = 'target'
editor.appendChild(target)
const controlsDiv = document.createElement('div')
controlsDiv.className = 'controls'
editor.appendChild(controlsDiv)
const filterConfig = [
{ name: 'blur', unit: 'px', min: 0, max: 20, step: 0.5, default: 0 },
{ name: 'brightness', unit: '', min: 0, max: 3, step: 0.1, default: 1 },
{ name: 'contrast', unit: '', min: 0, max: 4, step: 0.1, default: 1 },
{ name: 'grayscale', unit: '', min: 0, max: 1, step: 0.05, default: 0 },
{ name: 'saturate', unit: '', min: 0, max: 4, step: 0.1, default: 1 },
{ name: 'hue-rotate', unit: 'deg', min: 0, max: 360, step: 5, default: 0 },
]
const values = {}
filterConfig.forEach(cfg => { values[cfg.name] = cfg.default })
const output = document.createElement('pre')
function updateFilter() {
const parts = filterConfig
.filter(c => values[c.name] !== c.default)
.map(c => `${c.name}(${values[c.name]}${c.unit})`)
const filterStr = parts.length ? parts.join(' ') : 'none'
target.style.filter = filterStr
output.textContent = `filter: ${filterStr};`
}
filterConfig.forEach(cfg => {
const row = document.createElement('div')
row.className = 'control-row'
const label = document.createElement('label')
label.textContent = cfg.name
const input = document.createElement('input')
input.type = 'range'
input.min = cfg.min
input.max = cfg.max
input.step = cfg.step
input.value = cfg.default
const span = document.createElement('span')
span.textContent = cfg.default + cfg.unit
input.addEventListener('input', () => {
values[cfg.name] = parseFloat(input.value)
span.textContent = input.value + cfg.unit
updateFilter()
})
row.appendChild(label)
row.appendChild(input)
row.appendChild(span)
controlsDiv.appendChild(row)
})
controlsDiv.appendChild(output)
updateFilter()Создай страницу с фотогалереей и эффектами CSS-фильтров. По умолчанию изображения (замени цветными блоками) показываются в чёрно-белом виде (`grayscale(1)`). При наведении — полноцветные с яркостью 1.1 и насыщенностью 1.2. Добавь отдельную карточку с эффектом glassmorphism через `backdrop-filter: blur()`.
По умолчанию: `filter: grayscale(1) brightness(0.8)`. При `:hover`: `filter: grayscale(0) brightness(1.1) saturate(1.2)`. Для glassmorphism: `background: rgba(255,255,255,0.1)`, `backdrop-filter: blur(12px)`. Фон страницы тёмный, чтобы эффект стекла был виден.