SVG gradient sử dụng CSS


102

Tôi đang cố gắng áp dụng một gradient cho SVG rect phần tử .

Hiện tại, tôi đang sử dụng fillthuộc tính. Trong tệp CSS của tôi:

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

rectphần tử có màu tô chính xác khi xem trên trình duyệt.

Tuy nhiên, tôi muốn biết liệu tôi có thể áp dụng một gradient tuyến tính cho phần tử này không?

Câu trả lời:


95

Chỉ cần sử dụng trong CSS bất kỳ thứ gì bạn muốn sử dụng trong fill thuộc tính. Tất nhiên, điều này yêu cầu bạn phải xác định gradient tuyến tính ở đâu đó trong SVG của bạn.

Đây là một ví dụ đầy đủ:

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
Vì vậy, tôi đã tạo ra rằng gradient trong một file riêng biệt, và được sử dụng filltheo cách này: fill: url(../js/gradient.svg#MyGradient);. Đây có phải là hướng đi đúng?
Hrishikesh Choudhari

@HrishikeshChoudhari: Đúng, điều này đúng, nhưng Chrome và tôi nghĩ rằng Safari cũng không hỗ trợ các phần tử tham chiếu từ các tệp khác. Không chắc chắn về IE9 (không thể kiểm tra ngay bây giờ, chỉ cần thử).
Thomas W

53
Đối với bất kỳ ai đọc điều này và hỏi "điều gì về fill: linear-gradient (...)?" fillyêu cầu một <paint>cái được xây dựng xung quanh <color>lớp CSS2 . Nói cách khác, câu trả lời này hiện là cách duy nhất để thực hiện nó thông qua CSS tại thời điểm tôi viết bình luận này. Bạn cần thêm một linearGradientphần tử. Cuối cùng, xem qua Bản thảo làm việc w3 cho SVG2 , nó có vẻ như hỗ trợ cho linear-gradientquy tắc điền css chưa và có thể không đưa nó vào thông số kỹ thuật.
Arthur Weborg

Làm thế nào để thay đổi hướng trong trường hợp này?
AGamePlayer

1
@AwQiruiGuo Hãy xem MDN (cụ thể là gradientTransformthuộc tính)
Thomas W

34

Câu trả lời năm 2019

Với các thuộc tính css hoàn toàn mới, bạn có thể linh hoạt hơn nữa với các biến 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>

Chỉ cần đặt một biến được đặt tên cho mỗi biến stoptrong gradient và sau đó tùy chỉnh theo ý muốn trong css. Bạn thậm chí có thể thay đổi động các giá trị của chúng bằng javascript, như:

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

3
Không được hỗ trợ trong IE.
aoakeson

3
Thuộc tính tùy chỉnh CSS ở đây trong một thời gian rất dài, nếu bằng cách nào đó ai đó vẫn chưa sẵn sàng sử dụng chúng, thì anh ta sẽ không bao giờ sẵn sàng cho những thay đổi.
Maciej Kwas

1
@MaciejKwas, bạn đã nhầm. Các trình duyệt cũ không tồn tại mãi mãi nên các công ty chưa sẵn sàng bây giờ sẽ sẵn sàng sau đó. Và nếu ai đó không sẵn sàng loại bỏ một phần khán giả của mình, điều đó không có nghĩa là anh ta chưa sẵn sàng cho những thay đổi, điều đó có nghĩa là anh ta muốn tận dụng những thay đổi sau để giữ được lượng khán giả lớn hơn.
Finesse

19
@aoakeson IE đã chết. Kết thúc cuộc sống. Edge cũng đang chết dần, đây là câu trả lời cho năm 2019, vì vậy IE không nên tính đến. IE có thể làm giảm chất lượng bằng cách sử dụng một màu đồng nhất.
Ciprian

5
@aoakeson Tôi ngạc nhiên ngạc nhiên khi đi qua đó loại phản ứng trong năm 2019. Bạn sẽ ngây thơ như một nhà phát triển để đảm nhận hỗ trợ SVG trong IE trên mức này sẽ không bao giờ được hỗ trợ, hãy để một mình một nhà phát triển vừa chớm nở trên SO tạo cho bạn một cồng kềnh , câu trả lời đầy đủ cho một cái gì đó không cần thiết nếu bạn định hỗ trợ IE.
James Martin-Davies

18

Dựa trên những gì Finesse đã viết, đây là một cách đơn giản hơn để nhắm mục tiêu svg và thay đổi độ dốc của nó.

Đây là những gì bạn cần làm:

  1. Gán các lớp cho mỗi điểm dừng màu được xác định trong phần tử gradient.
  2. Nhắm mục tiêu css và thay đổi màu dừng cho mỗi điểm dừng đó bằng cách sử dụng các lớp đơn giản.
  3. Thắng lợi!

Một số lợi ích của việc sử dụng thay vì các lớp học :nth-childlà nó sẽ không bị ảnh hưởng nếu bạn sắp xếp lại các điểm dừng của mình. Ngoài ra, nó làm cho ý định của mỗi lớp rõ ràng - bạn sẽ không còn băn khoăn liệu mình cần màu xanh lam cho lớp đầu tiên hay lớp thứ hai.

Tôi đã thử nghiệm nó trên tất cả Chrome, Firefox và 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>

Xem ví dụ có thể chỉnh sửa tại đây: https://jsbin.com/gabuvisuhe/edit?html,css,output


Điều thiếu sót là bạn không biết chắc tên lớp dừng là gì và thứ tự của chúng. Trên thực tế, các giải pháp đều tốt như nhau, điểm khác biệt duy nhất là bộ chọn CSS.
Finesse

3
Tôi nghĩ đây là câu trả lời hiện đại tốt nhất cho câu hỏi OPs.
Elemental

9

Đây là một giải pháp mà bạn có thể thêm một gradient và thay đổi màu sắc của nó chỉ bằng 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

Cảm ơn tất cả mọi người, cho tất cả các câu trả lời chính xác của bạn.

Sử dụng svg trong một dom bóng, tôi thêm 3 gradient tuyến tính mà tôi cần trong svg, bên trong a. Tôi đặt quy tắc điền css trên thành phần web và điền od thừa kế thực hiện công việc.

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

xem bài kiểm tra của tôi trong codepen

Cái đầu tiên là SVG bình thường, cái thứ hai nằm bên trong một dom bóng.


-4

Dưới đây là cách đặt một linearGradient trên một phần tử đích:

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

Không có gì trong câu hỏi ngụ ý sử dụng php.
ACJ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.