SVG gradient using CSS

前端 未结 6 1259
粉色の甜心
粉色の甜心 2020-11-29 19:58

I\'m trying to get a gradient applied to an SVG rect element.

Currently, I\'m using the fill attribute. In my CSS file:

rec         


        
相关标签:
6条回答
  • 2020-11-29 20:05

    Thank you everyone, for all your precise replys.

    Using the svg in a shadow dom, I add the 3 linear gradients I need within the svg, inside a . I place the css fill rule on the web component and the inheritance od fill does the job.

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

    The first one is normal SVG, the second one is inside a shadow dom.

    0 讨论(0)
  • 2020-11-29 20:10

    Just use in the CSS whatever you would use in a fill attribute. Of course, this requires that you have defined the linear gradient somewhere in your SVG.

    Here is a complete example:

    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>

    0 讨论(0)
  • 2020-11-29 20:19

    2019 Answer

    With brand new css properties you can have even more flexibility with variables 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>

    Just set a named variable for each stop in gradient and then customize as you like in css. You can even change their values dynamically with javascript, like:

    document.querySelector('#header-shape-gradient').style.setProperty('--color-stop', "#f5f7f9");
    
    0 讨论(0)
  • Here is a solution where you can add a gradient and change its colours using only 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>

    0 讨论(0)
  • 2020-11-29 20:25

    Here is how to set a linearGradient on a target element:

    <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>
    
    0 讨论(0)
  • 2020-11-29 20:27

    Building on top of what Finesse wrote, here is a simpler way to target the svg and change it's gradient.

    This is what you need to do:

    1. Assign classes to each color stop defined in the gradient element.
    2. Target the css and change the stop-color for each of those stops using plain classes.
    3. Win!

    Some benefits of using classes instead of :nth-child is that it'll not be affected if you reorder your stops. Also, it makes the intent of each class clear - you'll be left wondering whether you needed a blue color on the first child or the second one.

    I've tested it on all Chrome, Firefox and 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>

    See an editable example here: https://jsbin.com/gabuvisuhe/edit?html,css,output

    0 讨论(0)
提交回复
热议问题