Using the linearGradient feature within an SVG to create a transitional effect on the Fill property

Looking to implement a stepper functionality, everything is working smoothly except for the transition on the fill.

let step = 0;
document.querySelector("button").addEventListener('click', () => {
   step++;
   document.querySelector("svg").style.fill = `url(#lg-step-${step})`
})
.stepper {
    transition-property: fill;
    transition-duration: 1s;
    transition-timing-function: ease-in-out;
}
<svg id="test_svg" viewBox="0 0 620 50" width="300" height="20" fill="url(#lg-step-0)" stroke="black" stroke-width="1" class="stepper">
    <path d="m 71 29 h -60 c -14 0 -14 -19 0 -19 h 60 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 60 c 14 0 14 19 0 19 h -60 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h 60 c 14 0 14 19 0 19 h -60 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0" />
    <linearGradient id="lg-step-0">
        <stop offset="0%" stop-color="blue" />
        <stop offset="6%" stop-color="blue" stop-opacity="60%" />
        <stop offset="6%" stop-color="transparent" />
    </linearGradient>
    <linearGradient id="lg-step-1" >
        <stop offset="0%" stop-color="blue" />
        <stop offset="14%" stop-color="blue" stop-opacity="60%"/>
        <stop offset="14%" stop-color="transparent" />
    </linearGradient>
    <linearGradient id="lg-step-2">
        <stop offset="0%" stop-color="blue" />
        <stop offset="50%" stop-color="blue" stop-opacity="60%" />
        <stop offset="50%" stop-color="transparent" />
    </linearGradient>
    <linearGradient id="lg-step-3">
        <stop offset="0%" stop-color="blue" />
        <stop offset="87%" stop-color="blue" stop-opacity="60%" />
        <stop offset="87%" stop-color="transparent" />
    </linearGradient>

</svg>
<button> Next step </button>

The JavaScript used here is just for testing purposes and not from my actual codebase.

Seeking help to achieve a smooth transition between all steps as outlined above. Any assistance would be greatly appreciated.

PS: Currently working with Blazor, so solutions requiring minimal JS are preferred.

Answer №1

transition doesn't work with strings or DOM subtrees, only numbers. If you want to animate the offset attribute of the <stop> element in SVG, you need to use SMIL animations, not CSS transitions.

offset is a pure XML attribute that can be animated with SMIL. You can achieve what you want by using SMIL animations, as demonstrated below:

let step = 0;
document.querySelector("button").addEventListener('click', () => {
   step++;
   document.querySelectorAll(`.lg-step-${step}`).forEach(el => {
      el.beginElement();
   })
})
<svg id="test_svg" viewBox="0 0 620 50" width="300" height="20" fill="url(#lg-step-0)" stroke="black" stroke-width="1" class="stepper">
    <path d="m 71 29 h -60 c -14 0 -14 -19 0 -19 h 60 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 60 c 14 0 14 19 0 19 h -60 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h 60 c 14 0 14 19 0 19 h -60 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0" />
    <linearGradient id="lg-step-0">
        <stop offset="0%" stop-color="blue" />
        <stop offset="6%" stop-color="blue" stop-opacity="60%">
            <animate class="lg-step-1" attributeName="offset" from=".06" to=".14"
                     begin="indefinite" dur="1s" fill="freeze"
                     calcMode="spline" keySplines="0.42, 0, 0.58, 1" />
            <animate class="lg-step-2" attributeName="offset" from=".14" to=".5"
                     begin="indefinite" dur="1s" fill="freeze"
                     calcMode="spline" keySplines="0.42, 0, 0.58, 1" />
            <animate class="lg-step-3" attributeName="offset" from=".5" to=".87"
                     begin="indefinite" dur="1s" fill="freeze"
                     calcMode="spline" keySplines="0.42, 0, 0.58, 1" />
        </stop>
        <stop offset="6%" stop-color="transparent">
            <animate class="lg-step-1" attributeName="offset" from=".04" to=".14"
                     begin="indefinite" dur="1s" fill="freeze"
                     calcMode="spline" keySplines="0.42, 0, 0.58, 1" />
            <animate class="lg-step-2" attributeName="offset" from=".14" to=".50"
                     begin="indefinite" dur="1s" fill="freeze"
                     calcMode="spline" keySplines="0.42, 0, 0.58, 1" />
            <animate class="lg-step-3" attributeName="offset" from=".5" to=".87"
                     begin="indefinite" dur="1s" fill="freeze"
                     calcMode="spline" keySplines="0.42, 0, 0.58, 1" />
        </stop>
    </linearGradient>
</svg>
<button> Next step </button>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The performance of Jquery Animate is acting strangely after the upgrade to version 1.11

Take a look at http://jsfiddle.net/integerz/k19x8L1b/2/ which uses version 1.7.x $(function () { $("#clickme").toggle(function () { $(this).parent().animate({right:'0px'}); }, function () { $(this).parent().animate({righ ...

Secondary menu

Is there a way to create a sub navigation menu that only changes once I click a link in the main navigation bar, without refreshing the entire page? Any help would be greatly appreciated. http://jsfiddle.net/qrn8Q/ Thank you. HTML Code: <header ...

The :empty selector is failing to function properly in @media print queries

Currently, I am working in Twig on Symphony and have encountered an issue with an empty div that needs to be hidden in print mode. <div class="form-fields__list"> </div> Surprisingly, the :empty selector works perfectly fine on the screen, bu ...

What is the best way to navigate through an HTML node tree, including all of its sub elements, when walking through

Do you know of a way to iterate through the entire hierarchy of HTML elements and check each one for attributes and more without using JavaScript? We currently have a JavaScript solution that iterates through each child element and all their descendants. ...

Tips on customizing default Polymer CSS

Currently, the core-toolbar features an indent class that shifts the title to the right by 60px. However, material design guidelines suggest that the margin should actually be 80px (oddly enough, the number 60 is not mentioned in the documentation). I cou ...

Learn the step-by-step process of cropping and zooming an image using the react-image-crop

I am looking to implement zooming and cropping functionality for an image using react-image-crop instead of react-easy-crop. Currently, the cropping does not take into account the zoom level set by ReactCrop's scale property. I want to be able to zo ...

preserve functionality when switching between pages

I have created two simple functions that can change the background color of the body. <script type="text/javascript"> function switchBackground(color){ document.body.bgColor=color; } </script> I am using links with onclick to execute thes ...

Preventing the use of scripting tags in text boxes

I'm currently trying to integrate the post feature on my website using codeigniter (PHP). However, I've run into an issue where when I input and submit the following code: <script> alert("aaaa"); </script> The JavaScript starts exec ...

Utilize multiple background images in CSS with a set of three unique images

I have inserted three images into the background of my website's body. Two of them are displaying correctly (one with repeat-y), but the third one is not working. I've tried searching a lot but couldn't find a solution. body { backgr ...

"Angular 6: A Guide to Customizing Text Colors Based on Status

I have a view on angular just like this: https://i.sstatic.net/JimWN.png And this is my dashboard.component.ts: export class DashboardComponent implements OnInit { tablePresetColumns; tablePresetData; ngOnInit() { this.tablePresetColumns = [{id: ...

The integration of a side panel with a chrome extension is experiencing issues

I am working on a chrome extension with the following functionalities - Extract URL path from a specific webpage. (The webpage's URL remains constant) Open this URL in a new tab. It can be either http:// or https://. Embed an iframe containing a sim ...

The issue with res.sendFile is that it is failing to display

I have encountered an issue while attempting to render HTML with res.sendFile using an absolute path. The encoded HTML is being displayed unrendered within a pre tag in the response. Below is the express code I am currently using: app.get('/', ( ...

Unable to use Selenium web driver for C# to choose an element by its tag name

Currently, I am utilizing Selenium Web Driver in C# to interact with Google Chrome browser. However, when attempting to retrieve the inner HTML (text) of a specific element as shown in the provided HTML snippet below, an error message "no such element ...

Achieving a layered effect with elements overlapping onto another div

Looking for a way to create a design where the text in id="text-field" overlaps with id="image-field". Need some guidance on how to achieve this effect. Any help is appreciated. <!DOCTYPE html> <html> <body> <div class=" ...

The initial item in the Materializecss slider is failing to display

Currently, I am attempting to implement materialize slider with skrollr. The setup is functional; however, only the first item of the slider is set to opacity: 0 initially. https://i.stack.imgur.com/urSww.jpg After a brief delay, the second item becomes ...

What is the optimal unit to employ in CSS - percentages or pixels?

As someone who is not well-versed in CSS, I strive to create a design that will appear visually appealing across all browsers and screen resolutions. I have observed that certain websites construct their designs using percentages for properties like width, ...

The drop-down links vanish into the depths of the webpage's body

Can someone assist with my drop-down menu issue for the link "services"? The link disappears behind the page content when I try to modify it. Any help would be appreciated, thank you! This is the CSS: .bodycontent { margin: 0 25% 0 25%; ...

Do you need to align images side by side and have clickable images positioned beneath each one?

After searching high and low, I couldn't find a similar question. My goal is to transform this from a vertical layout to a horizontal one: https://i.stack.imgur.com/4kZNM.png Check out the code snippet below: ghost<br class="newline"> <img ...

Change the color of the menu icon based on the specified HTML class or attribute

I'm trying to create a fixed menu that changes color depending on the background of different sections. Currently, I am using a data-color attribute but I am struggling with removing and adding the class to #open-button. Adding the class works fine, ...

Enhancing List Numbers with CSS Styling

Is there a way to customize the appearance of numbered lists? I created an ordered list and would like to modify the numbering style To remove the bullets And adjust the color and background ...