Градієнт SVG за допомогою CSS


102

Я намагаюся отримати градієнт, застосований до rectелемента SVG .

В даний час я використовую fillатрибут. У моєму файлі CSS:

rect {
    cursor: pointer;
    shape-rendering: crispEdges;
    fill: #a71a2e;
}

І rectелемент має правильний колір заливки при перегляді в браузері.

Однак я хотів би знати, чи можу я застосувати до цього елемента лінійний градієнт?

Відповіді:


95

Просто використовуйте в CSS все, що ви б використовували в fillатрибуті. Звичайно, для цього потрібно, щоб ви визначили лінійний градієнт десь у своєму SVG.

Ось повний приклад:

rect {
    cursor: pointer;
    shape-rendering: crispEdges;
    fill: url(#MyGradient);
}
<svg width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
      <style type="text/css">
        rect{fill:url(#MyGradient)}
      </style>
      <defs>
        <linearGradient id="MyGradient">
          <stop offset="5%" stop-color="#F60" />
          <stop offset="95%" stop-color="#FF6" />
        </linearGradient>
      </defs>
      
      <rect width="100" height="50"/>
    </svg>


2
Так що я створив цей градієнт в окремому файлі, і використовується fillнаступним чином: fill: url(../js/gradient.svg#MyGradient);. Це правильний шлях?
— Хришікеш Чудхарі

@HrishikeshChoudhari: Так, це правильно, але Chrome, і я думаю, що Safari також не підтримує посилання на елементи з інших файлів. Не впевнений щодо IE9 (зараз не вдається протестувати, просто спробуйте).
— Thomas W

53
Кожному, хто прочитає це і запитає "а що fill: linear-gradient (...)?" fillвимагає a, <paint>який побудований навколо <color>класу CSS2 . Іншими словами, ця відповідь на даний момент є єдиним способом зробити це за допомогою CSS на момент написання цього коментаря. Вам потрібно додати linearGradientелемент. Нарешті, переглядаючи робочий проект w3 для SVG2 , виявляється, що підтримка linear-gradientправила заповнення css не має і, можливо, не потрапляє в специфікацію.
— Артур Веборг

Як змінити напрямок у цьому випадку?
— AGamePlayer

1
@AwQiruiGuo Погляньте на MDN (зокрема, на gradientTransformатрибут)
— Thomas W

34

Відповідь 2019

Завдяки абсолютно новим властивостям css ви можете отримати ще більшу гнучкість із змінними aka custom properties

.shape {
  width:500px;
  height:200px;
}

.shape .gradient-bg {
  fill: url(#header-shape-gradient) #fff;
}

#header-shape-gradient {
  --color-stop: #f12c06;
  --color-bot: #faed34;
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" class="shape">
  <defs>
    <linearGradient id="header-shape-gradient" x2="0.35" y2="1">
        <stop offset="0%" stop-color="var(--color-stop)" />
        <stop offset="30%" stop-color="var(--color-stop)" />
        <stop offset="100%" stop-color="var(--color-bot)" />
      </linearGradient>
  </defs>
  <g>
    <polygon class="gradient-bg" points="0,0 100,0 0,66" />
  </g>
</svg>

Просто встановіть іменовану змінну для кожного stopз градієнтів, а потім налаштуйте, як вам подобається в css. Ви навіть можете динамічно змінювати їх значення за допомогою JavaScript, наприклад:

document.querySelector('#header-shape-gradient').style.setProperty('--color-stop', "#f5f7f9");

3
Не підтримується в IE.
— aoakeson

3
Спеціальні властивості CSS знаходяться тут дуже довго, якщо хтось ще не готовий їх використовувати, то він ніколи не буде готовий до змін.
— Maciej

1
@MaciejKwas, ти помиляєшся. Старі браузери не залишаються назавжди, тому компанії, які не готові зараз, будуть готові тоді. І якщо хтось не готовий відкинути частину своєї аудиторії, це не означає, що він не готовий до змін, це означає, що він воліє використовувати зміни пізніше, щоб утримати більшу аудиторію.
— Finesse

19
@aoakeson IE мертвий. Кінець піднятий. Edge також вмирає, це відповідь 2019 року, тому IE не слід враховувати. IE може виграшно погіршити використання суцільного кольору.
— Ciprian

5
@aoakeson Я напрочуд здивований тим, що натрапив на таку відповідь у 2019 році. Ви були б наївними як розробник, коли б підтримували підтримку SVG в IE на цьому рівні , не кажучи вже про початківця розробника на SO, який дасть вам роздутий , полізаповнена відповідь на щось непотрібне, якщо ви маєте намір підтримувати IE.
— Джеймс Мартін-Девіс,

18

Спираючись на те, що писав Finesse, ось простіший спосіб націлити на svg і змінити його градієнт.

Це те, що вам потрібно зробити:

  1. Призначте класи для кожної зупинки кольору, визначеної в елементі градієнта.
  2. Націліть css і змініть колір зупинки для кожної з цих зупинок, використовуючи звичайні класи.
  3. Перемагай!

Деякі переваги використання класів замість того :nth-child, що це не вплине, якщо ви зміните порядок зупинок. Крім того, це чітко визначає наміри кожного класу - вам залишатиметься цікавим, чи потрібен вам синій колір для першої дитини чи для другого.

Я протестував його на всіх Chrome, Firefox та IE11:

.main-stop {
  stop-color: red;
}
.alt-stop {
  stop-color: green;
}
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <linearGradient id="gradient">
    <stop class="main-stop" offset="0%" />
    <stop class="alt-stop" offset="100%" />
  </linearGradient>
  <rect width="100" height="50" fill="url(#gradient)" />
</svg>

Дивіться приклад для редагування тут: https://jsbin.com/gabuvisuhe/edit?html,css,output


Недолік полягає в тому, що ви точно не знаєте, які назви класів зупинок і який порядок вони мають. Насправді, рішення однакові добрі, єдина відмінність - селектори CSS.
— Finesse

3
Я думаю, що це найкраща сучасна відповідь на питання ОП.
— Елементаль

9

Ось рішення, де ви можете додати градієнт і змінити його кольори, використовуючи лише CSS:

// JS is not required for the solution. It's used only for the interactive demo.
const svg = document.querySelector('svg');
document.querySelector('#greenButton').addEventListener('click', () => svg.setAttribute('class', 'green'));
document.querySelector('#redButton').addEventListener('click', () => svg.setAttribute('class', 'red'));
svg.green stop:nth-child(1) {
  stop-color: #60c50b;
}
svg.green stop:nth-child(2) {
  stop-color: #139a26;
}

svg.red stop:nth-child(1) {
  stop-color: #c84f31;
}
svg.red stop:nth-child(2) {
  stop-color: #dA3448;
}
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <linearGradient id="gradient">
    <stop offset="0%" />
    <stop offset="100%" />
  </linearGradient>
  <rect width="100" height="50" fill="url(#gradient)" />
</svg>

<br/>
<button id="greenButton">Green</button>
<button id="redButton">Red</button>


2

Дякую всім за всі ваші точні відповіді.

Використовуючи svg у тіньовому домі, я додаю 3 лінійні градієнти, які мені потрібні, у svg, всередині a. Я розміщую правило заповнення css на веб-компоненті, і спадщина od fill виконує цю роботу.

<svg viewbox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
  <path
    d="m258 0c-45 0-83 38-83 83 0 45 37 83 83 83 45 0 83-39 83-84 0-45-38-82-83-82zm-85 204c-13 0-24 10-24 23v48c0 13 11 23 24 23h23v119h-23c-13 0-24 11-24 24l-0 47c0 13 11 24 24 24h168c13 0 24-11 24-24l0-47c0-13-11-24-24-24h-21v-190c0-13-11-23-24-23h-123z"></path>
</svg>

<svg height="0" width="0">
  <defs>
    <linearGradient id="lgrad-p" gradientTransform="rotate(75)"><stop offset="45%" stop-color="#4169e1"></stop><stop offset="99%" stop-color="#c44764"></stop></linearGradient>
    <linearGradient id="lgrad-s" gradientTransform="rotate(75)"><stop offset="45%" stop-color="#ef3c3a"></stop><stop offset="99%" stop-color="#6d5eb7"></stop></linearGradient>
    <linearGradient id="lgrad-g" gradientTransform="rotate(75)"><stop offset="45%" stop-color="#585f74"></stop><stop offset="99%" stop-color="#b6bbc8"></stop></linearGradient>
  </defs>
</svg>

<div></div>

<style>
  :first-child {
    height:150px;
    width:150px;
    fill:url(#lgrad-p) blue;
  }
  div{
    position:relative;
    width:150px;
    height:150px;
    fill:url(#lgrad-s) red;
  }
</style>
<script>
  const shadow = document.querySelector('div').attachShadow({mode: 'open'});
  shadow.innerHTML="<svg viewbox=\"0 0 512 512\">\
    <path d=\"m258 0c-45 0-83 38-83 83 0 45 37 83 83 83 45 0 83-39 83-84 0-45-38-82-83-82zm-85 204c-13 0-24 10-24 23v48c0 13 11 23 24 23h23v119h-23c-13 0-24 11-24 24l-0 47c0 13 11 24 24 24h168c13 0 24-11 24-24l0-47c0-13-11-24-24-24h-21v-190c0-13-11-23-24-23h-123z\"></path>\
  </svg>\
  <svg height=\"0\">\
  <defs>\
    <linearGradient id=\"lgrad-s\" gradientTransform=\"rotate(75)\"><stop offset=\"45%\" stop-color=\"#ef3c3a\"></stop><stop offset=\"99%\" stop-color=\"#6d5eb7\"></stop></linearGradient>\
    <linearGradient id=\"lgrad-g\" gradientTransform=\"rotate(75)\"><stop offset=\"45%\" stop-color=\"#585f74\"></stop><stop offset=\"99%\" stop-color=\"#b6bbc8\"></stop></linearGradient>\
  </defs>\
</svg>\
";
</script>

див. мій тест в codepen

Перший - звичайний SVG, другий - всередині тіньового купола.


-4

Ось як встановити linearGradient для цільового елемента:

<style type="text/css">
    path{fill:url('#MyGradient')}
</style>
<defs>
    <linearGradient id="MyGradient">
        <stop offset="0%" stop-color="#e4e4e3" ></stop>
        <stop offset="80%" stop-color="#fff" ></stop>
    </linearGradient>
</defs>

Ніщо в питанні не передбачає використання php.
— ACJ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.