Градієнт 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.