I'm setting up a design system in NextJS14 (React). We are using CSS modules and have all colors stored in CSS variables (custom properties).
We have these nice-looking buttons in our Figma design. I want to use the exported SVG for the shape of our text buttons. preview of custom button shape svg
I made some progress by setting the background-image:
to the url of the SVG. However, I have not found a way to dynamically change the fill and stroke colors of the SVG based on the props passed into the custom Button component.
Here are some options. In your case I guess that the first two examples could be used. The last one is an alternative approach that only works in some cases.
Embed the SVG into the HTML and style the SVG elements using CSS.
button.orange rect {
fill: orange;
}
button.lime rect {
fill: lime;
}
button {
background-color: transparent;
border: none;
display: grid;
}
button svg {
grid-column: 1;
grid-row: 1;
align-self: center;
}
button span {
grid-column: 1;
grid-row: 1;
align-self: center;
padding: 0 1em;
}
<button class="orange">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 20">
<rect width="60" height="20" rx="5" fill="white" />
</svg>
<span>Button</span>
</button>
<button class="lime">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 20">
<rect width="60" height="20" rx="5" fill="white" />
</svg>
<span>Button</span>
</button>
Just repeat creating different CSS selectors with different background images.
button.orange {
fill: orange;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 20"><rect width="60" height="20" rx="5" fill="orange" /></svg>');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
button.lime {
fill: orange;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 20"><rect width="60" height="20" rx="5" fill="lime" /></svg>');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
button {
background-color: transparent;
border: none;
display: grid;
}
button svg {
grid-column: 1;
grid-row: 1;
align-self: center;
}
button span {
grid-column: 1;
grid-row: 1;
align-self: center;
padding: .2em 1em;
}
<button class="orange">
<span>Button</span>
</button>
<button class="lime">
<span>Button</span>
</button>
Combine a background image (the SVG document) with a solid background color defined in CSS. The SVG image is just a gradient going from transparent to white.
button.gradient01 {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxkZWZzPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJnMDEiIGdyYWRpZW50VHJhbnNmb3JtPSJyb3RhdGUoOTApIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1vcGFjaXR5PSIwIiBzdG9wLWNvbG9yPSJ3aGl0ZSIgLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLW9wYWNpdHk9IjEiIHN0b3AtY29sb3I9IndoaXRlIiAvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICA8L2RlZnM+CiAgPHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNnMDEpIiAvPgo8L3N2Zz4=');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
button.orange {
background-color: orange;
}
button.lime {
background-color: lime;
}
button {
background-color: transparent;
border: none;
display: grid;
border-radius: 5px;
}
button svg {
grid-column: 1;
grid-row: 1;
align-self: center;
}
button span {
grid-column: 1;
grid-row: 1;
align-self: center;
padding: .2em 1em;
}
<button class="orange gradient01">
<span>Button</span>
</button>
<button class="lime gradient01">
<span>Button</span>
</button>
<p>The SVG used as background:</p>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="g01" gradientTransform="rotate(90)">
<stop offset="0%" stop-opacity="0" stop-color="white" />
<stop offset="100%" stop-opacity="1" stop-color="white" />
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#g01)" />
</svg>