Gradien SVG menggunakan CSS

104

Saya mencoba menerapkan gradien ke rectelemen SVG .

Saat ini, saya menggunakan fillatribut. Di file CSS saya:

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

Dan rectelemen memiliki warna isian yang benar jika dilihat di browser.

Namun, saya ingin tahu apakah saya dapat menerapkan gradien linier ke elemen ini?

Hrishikesh Choudhari
sumber

Jawaban:

96

Cukup gunakan di CSS apa pun yang akan Anda gunakan dalam sebuah fillatribut. Tentu saja, ini mengharuskan Anda untuk mendefinisikan gradien linier di suatu tempat di SVG Anda.

Berikut contoh lengkapnya:

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>

Thomas W.
sumber
2
Jadi saya dibuat yang gradien dalam file terpisah, dan digunakan filldengan cara ini: fill: url(../js/gradient.svg#MyGradient);. Apakah ini jalan yang benar?
Hrishikesh Choudhari
@HrishikeshChoudhari: Ya, ini benar, tetapi Chrome dan saya pikir Safari juga tidak mendukung elemen referensi dari file lain. Tidak yakin tentang IE9 (tidak dapat menguji sekarang, coba saja).
Thomas W
53
Kepada siapa pun yang membaca ini dan bertanya "tentang apa fill: linear-gradient (...)?" fillmembutuhkan <paint>yang dibangun di sekitar <color>kelas CSS2 . Dengan kata lain, jawaban ini saat ini adalah satu-satunya cara untuk melakukannya melalui CSS pada saat saya menulis komentar ini. Anda perlu menambahkan linearGradientelemen. Terakhir, melalui w3 Working Draft untuk SVG2 , tampaknya dukungan untuk linear-gradientaturan css isi belum dan mungkin tidak berhasil masuk ke dalam spesifikasi.
Arthur Weborg
Bagaimana cara mengubah arah dalam kasus ini?
AGamePlayer
1
@AwQiruiGuo Lihat MDN (khususnya gradientTransformatributnya)
Thomas W
34

Jawaban 2019

Dengan properti css baru, Anda dapat memiliki lebih banyak fleksibilitas dengan variabel alias 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>

Cukup atur variabel bernama untuk masing-masing stopdalam gradien dan kemudian sesuaikan sesuka Anda di css. Anda bahkan dapat mengubah nilainya secara dinamis dengan javascript, seperti:

document.querySelector('#header-shape-gradient').style.setProperty('--color-stop', "#f5f7f9");
Maciej Kwas
sumber
3
Tidak didukung Di IE.
aoakeson
3
Properti Kustom CSS ada di sini untuk waktu yang sangat lama, jika seseorang belum siap untuk menggunakannya, maka dia tidak akan pernah siap untuk perubahan.
Maciej Kwas
1
@MaciejKwas, Anda salah. Browser lama tidak bertahan selamanya sehingga perusahaan yang belum siap sekarang akan siap. Dan jika seseorang tidak siap untuk membuang sebagian dari audiensnya, itu tidak berarti bahwa dia tidak siap untuk perubahan, itu berarti dia lebih suka memanfaatkan perubahan tersebut nanti untuk mempertahankan audiens yang lebih besar.
Finesse
19
@aoakeson IE sudah mati. Akhir kehidupan. Edge juga sekarat, ini adalah jawaban tahun 2019, jadi IE seharusnya tidak dihitung. IE dapat menurunkan kualitas dengan baik menggunakan warna solid.
Ciprian
5
@aoakeson Saya sangat terkejut menemukan tanggapan seperti itu di tahun 2019. Anda akan naif sebagai pengembang untuk menganggap dukungan SVG di IE pada tingkat ini akan pernah didukung, apalagi pengembang pemula di SO memberi Anda pembengkakan , jawaban polyfilled untuk sesuatu yang tidak perlu diperlukan jika Anda berniat untuk mendukung IE.
James Martin-Davies
18

Membangun di atas apa yang Finesse tulis, berikut adalah cara yang lebih sederhana untuk menargetkan svg dan mengubah gradiennya.

Ini adalah hal yang perlu kamu lakukan:

  1. Tetapkan kelas untuk setiap perhentian warna yang ditentukan dalam elemen gradien.
  2. Targetkan css dan ubah warna stop untuk masing-masing stop menggunakan class biasa.
  3. Menang!

Beberapa manfaat menggunakan kelas, bukan :nth-childadalah bahwa hal itu tidak akan terpengaruh jika Anda menyusun ulang perhentian Anda. Juga, itu membuat maksud dari setiap kelas menjadi jelas - Anda akan bertanya-tanya apakah Anda membutuhkan warna biru untuk anak pertama atau kedua.

Saya telah mengujinya di semua Chrome, Firefox dan 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>

Lihat contoh yang dapat diedit di sini: https://jsbin.com/gabuvisuhe/edit?html,css,output

kumarharsh
sumber
Kekurangannya adalah Anda tidak tahu pasti apa nama kelas berhenti dan urutannya. Sebenarnya, solusinya sama bagusnya, satu-satunya perbedaan adalah pemilih CSS.
Finesse
3
Saya pikir ini adalah jawaban modern terbaik untuk pertanyaan OP.
Elemental
9

Berikut adalah solusi di mana Anda dapat menambahkan gradien dan mengubah warnanya hanya dengan 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>

Kemahiran
sumber
2

Terima kasih semuanya, untuk semua balasan tepat Anda.

Menggunakan svg di shadow dom, saya menambahkan 3 gradien linier yang saya butuhkan di dalam svg, di dalam a. Saya menempatkan aturan css fill pada komponen web dan warisan od fill melakukan pekerjaan itu.

<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>

lihat pengujian saya di codepen

Yang pertama adalah SVG normal, yang kedua ada di dalam shadow dom.

Roland Gautier
sumber
-4

Berikut adalah cara menyetel LinearGradient pada elemen target:

<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>
axelparatre.dll
sumber
Tidak ada pertanyaan yang menyiratkan penggunaan php.
ACJ