Функція paint() у CSS — власне тло елемента з Paint API


Опис

CSS-функція paint() дозволяє використовувати додаткове джерело малюнка для фарбування елементів веб-сторінки. Вона відкриває перед розробниками нові можливості для створення ефектів фарбування, які ідуть далеко за рамки традиційних кольорів та градієнтів. Вона пропонує гнучкіший підхід до дизайну, оскільки дозволяє інтегрувати різноманітні візуальні ресурси безпосередньо у стилі веб-сторінки.

Для коректної роботи paint() необхідно вказати джерело малюнка за допомогою параметра paint-source. Це може бути:

  • URL-адреса зображення,
  • малюнок SVG,
  • інша властивість CSS, яка пов'язана з фарбуванням (наприклад, var(--color)).
  • Функція paint() передає це джерело малюнка як значення властивості фарбування елемента.

Приклад використання:

background-color: paint(url("image.png"));

Тут ми встановлюємо фоновий колір елемента, використовуючи зображення "image.png" як джерело фарбування.

автор: Bond

Загальний опис

автор: NagarD

Порада

Використовуйте вирази, щоб динамічно змінювати джерело малюнка для paint(). Наприклад, paint(var(--image-source)) дозволяє використовувати змінну CSS для вибору джерела малюнка.

автор: Bond
Порада

Експериментуйте з різними типами джерел малюнків, такими як зображення, малюнок SVG або навіть градієнти, щоб отримати цікаві ефекти.

автор: Bond

Синтаксис

paint(<paint-source>);

Функція paint може отримувати єдине значення:

<paint-source>

URL-адреса зображення або малюнок SVG.

автор: Bond

Значення без задання: none

Переглядачі

Підтримка: стаціонарні переглядачі
Переглядач Google Chrome Opera Microsoft EDGE
65 52 79
Підтримка: мобільні переглядачі
Переглядач Mobile Google Android Mobile Google Chrome
65 65

Приклади

+ запропонувати свій приклад у пісочниці

Той самий блок двічі: у переглядачі з підтримкою paint() він отримає штрихування, намальоване воркліта, у решті — градієнт із попереднього рядка того самого правила. Скрипт друкує, що саме сталося: чи є CSS.paintWorklet, чи прийнято оголошення й чи вдалося зареєструвати модуль.

HTML

<h4 class="cap">Блок із <code>paint()</code> і запасним градієнтом</h4>
<div class="demo" id="demo">
    <strong>background-image</strong><br>
    перший рядок правила — градієнт,<br>
    другий — <code>paint(hatch)</code>
</div>

<h4 class="cap">Що переглядач із цим зробив</h4>
<table id="report">
    <thead><tr><th>перевірка</th><th>результат</th></tr></thead>
    <tbody></tbody>
</table>
<p class="note" id="vysnovok"></p>

CSS

.demo {
    --hatch-color: #2f6fd0;
    width: 280px;
    padding: 24px 18px;
    border: 1px solid #b9c6d8;
    border-radius: 6px;
    color: #1d3a6b;
    line-height: 1.5;

    /* 1) запасний варіант — його побачать Firefox і Safari */
    background-image: repeating-linear-gradient(45deg, #eef4ff 0 8px, #dbe6f5 8px 16px);
    /* 2) а це переб'є попередній рядок там, де paint() підтримується */
    background-image: paint(hatch);
}

table {
    margin-top: 6px;
    border-collapse: collapse;
    font-size: .88rem;
}

th,
td {
    padding: 4px 9px;
    border: 1px solid #b9c6d8;
    text-align: left;
}

th {
    background: #eef4ff;
}

.cap {
    margin: 22px 0 8px;
    font-size: 1rem;
    color: #5a6472;
}

.note {
    max-width: 560px;
    color: #5a6472;
    font-size: .9em;
}

code {
    background: #eef4ff;
    border-radius: 3px;
    padding: 0 4px;
}

JS

const tbody = document.querySelector('#report tbody');
const ryadok = (nazva, znachennya) => {
    const row = tbody.insertRow();
    row.insertCell().textContent = nazva;
    row.insertCell().textContent = String(znachennya);
    console.log(nazva, '->', znachennya);
};

const jePidtrymka = typeof CSS !== 'undefined' && 'paintWorklet' in CSS;

ryadok('typeof CSS.paintWorklet', typeof CSS.paintWorklet); // → undefined у Firefox
ryadok('CSS.supports("background-image", "paint(hatch)")',
    CSS.supports('background-image', 'paint(hatch)')); // → false у Firefox
ryadok('CSS.supports("background-image", "url(x.png)")',
    CSS.supports('background-image', 'url(x.png)')); // → true скрізь
ryadok('CSS.registerProperty існує', typeof CSS.registerProperty); // → function навіть без paint()
ryadok('обчислене background-image блока',
    getComputedStyle(document.getElementById('demo')).backgroundImage.slice(0, 60) + '…');

// сам воркліт: окремий модуль, тому збираємо його як blob-адресу
const MODUL = `
registerPaint('hatch', class {
    static get inputProperties() { return ['--hatch-color']; }
    paint(ctx, geom, props) {
        ctx.strokeStyle = props.get('--hatch-color').toString().trim() || '#2f6fd0';
        ctx.lineWidth = 3;
        for (let x = -geom.height; x < geom.width; x += 12) {
            ctx.beginPath();
            ctx.moveTo(x, 0);
            ctx.lineTo(x + geom.height, geom.height);
            ctx.stroke();
        }
    }
});
`;

const vysnovok = document.getElementById('vysnovok');

if (!jePidtrymka) {
    vysnovok.textContent = 'Цей переглядач не знає paint(): друге оголошення в правилі '
        + 'відкинуто, і блок показує градієнт із першого рядка. Саме так це й має працювати.';
    console.log('paint() недоступний — показано запасний градієнт'); // → саме цей рядок у Firefox
} else {
    const adresa = URL.createObjectURL(new Blob([MODUL], { type: 'text/javascript' }));
    CSS.paintWorklet.addModule(adresa).then(() => {
        vysnovok.textContent = 'Воркліт зареєстровано — блок малює скрипт, а не градієнт.';
        console.log('воркліт «hatch» зареєстровано'); // → у Chrome
    }).catch((e) => {
        vysnovok.textContent = 'paint() є, але модуль не завантажився: ' + e.name;
        console.log('addModule відхилено:', e.name, e.message);
    });
}
автор: NagarD

HTML

<div id="description">
  <h2>Приклад 1: зміна елемента за допомогою функції paint()</h2>
  <p>Наведіть курсор на елемент, щоб побачити зміну.</p>
</div>

<div id="result">
  <div class="image-container">
    <div class="image paint"></div>
  </div>
</div>

CSS

#description {
  background-color: #f2f2f2;
  padding: 20px;
  font-family: Arial, sans-serif;
}

#result {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px;
}

.image-container {
  position: relative;
}

.image {
  width: 200px;
  height: 200px;
  background-size: cover;
  background-position: center;
}

.paint {
  background-image: -webkit-paint(url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 40 40' preserveAspectRatio='none'%3E%3Crect width='40' height='40' fill='%23264653'/%3E%3Cpath d='M0 40 12 18 22 30 30 22 40 40Z' fill='%232a9d8f'/%3E%3Ccircle cx='30' cy='9' r='5' fill='%23e9c46a'/%3E%3C/svg%3E"));
  background-image: paint(url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 40 40' preserveAspectRatio='none'%3E%3Crect width='40' height='40' fill='%23264653'/%3E%3Cpath d='M0 40 12 18 22 30 30 22 40 40Z' fill='%232a9d8f'/%3E%3Ccircle cx='30' cy='9' r='5' fill='%23e9c46a'/%3E%3C/svg%3E"));
  transition: background-image 0.3s ease;
}

.paint:hover {
  background-image: -webkit-paint(url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 40 40' preserveAspectRatio='none'%3E%3Crect width='40' height='40' fill='%23415a77'/%3E%3Cpath d='M0 40 12 18 22 30 30 22 40 40Z' fill='%23778da9'/%3E%3Ccircle cx='30' cy='9' r='5' fill='%23e0e1dd'/%3E%3C/svg%3E"));
  background-image: paint(url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 40 40' preserveAspectRatio='none'%3E%3Crect width='40' height='40' fill='%23415a77'/%3E%3Cpath d='M0 40 12 18 22 30 30 22 40 40Z' fill='%23778da9'/%3E%3Ccircle cx='30' cy='9' r='5' fill='%23e0e1dd'/%3E%3C/svg%3E"));
}
автор: Bond

HTML

<div id="description">
  <h2>Приклад 2: елементи з різними фоновими зображеннями</h2>
  <p>Один елемент використовує функцію paint() для зміни фонового зображення.</p>
</div>

<div id="result">
  <div class="image-container">
    <div class="image"></div>
    <div class="image paint"></div>
  </div>
</div>

CSS

#description {
  background-color: #f2f2f2;
  padding: 20px;
  font-family: Arial, sans-serif;
}

#result {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px;
}

.image-container {
  display: flex;
}

.image {
  width: 200px;
  height: 200px;
  margin-right: 20px;
  background-color: red;
}

.paint {
  background-image: -webkit-paint(url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 40 40' preserveAspectRatio='none'%3E%3Crect width='40' height='40' fill='%23264653'/%3E%3Cpath d='M0 40 12 18 22 30 30 22 40 40Z' fill='%232a9d8f'/%3E%3Ccircle cx='30' cy='9' r='5' fill='%23e9c46a'/%3E%3C/svg%3E"));
  background-image: paint(url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 40 40' preserveAspectRatio='none'%3E%3Crect width='40' height='40' fill='%23264653'/%3E%3Cpath d='M0 40 12 18 22 30 30 22 40 40Z' fill='%232a9d8f'/%3E%3Ccircle cx='30' cy='9' r='5' fill='%23e9c46a'/%3E%3C/svg%3E"));
}
автор: Bond

Коментарі

Коментарів ще немає — будьте першим!

Відповідь для

Як форматувати текст?
Пишемо Виходить
**важливо**
*акцент*
~~застаріле~~
Виділення в тексті. Те саме роблять кнопки панелі, що спливає над виділеним.
## Як працює каскад
### Порядок оголошень
Заголовки всередині тексту. Найбільший не потрібен — він у сторінки вже є.
[[css/property/color]] Посилання на сторінку довідника. Наберіть [[ — поле веде сходинками (розділ → тип → сторінка), а хибний ключ підкреслить хвилею.
[[!sandbox/S0oh1hBm]] Живий приклад окремим рядком — саме вікно результату. Той самий ключ зі знаком !: наберіть [[! і дійдіть сходинками до потрібної сторінки, список покаже її приклади.
[MDN](https://developer.mozilla.org) Посилання на чужий сайт.
![Схема каскаду](https://site.com/схема.png) Картинка. Опис обов'язковий: його читають пошуковик і незрячі.
Задайте `display: grid` контейнеру Код усередині речення.
```css
.card { display: grid }
```
Код блоком. Мова після трьох лапок вмикає підсвітку.
- Походження
1. Походження
Перелік: маркований і нумерований.
- [ ] дописати приклади
- [x] перевірити в Firefox
Перелік завдань із галочками. Пробіл у порожніх дужках обов'язковий.
> Порядок важить лише за рівної ваги. Цитата на всю ширину абзацу.
Специфічність
: вага селектора; більша перемагає
Список означень: термін, а під ним пояснення з відступом. Пробіл після двокрапки обов'язковий.
Каскад має три критерії[^1]
[^1]: Походження, специфічність, порядок.
Виноска: номер у тексті, примітка внизу сторінки. Без згадки [^1] у тексті примітка не з'явиться.
Відповідь: ||сорок два|| Ховає те, що між рисками: читач бачить на цьому місці розмиту пляму, а решта речення лишається звичайною. Клац — і текст відкрито.
|| Показати рішення
Задайте контейнеру `display: grid`.
||
Ховає цілі абзаци. На сторінці видно лише підпис із першого рядка («Показати рішення»), решта розгортається клацанням по ньому. Закривні риски — окремим рядком.
Порожній рядок Новий абзац. Щоб перенести рядок усередині абзацу, поставте \ в його кінці.

Увійдіть — коментар з'явиться одразу, без капчі й очікування перевірки.

Правка
Зворотний зв'язок
Вхід