The intended effect of the code below is that it displays 2 red circles that turn to gray if the mouse hovers over them:
.hovered {
fill: gray !important; /* Apply the gray fill color */
stroke: blue !important; /* Add a blue border */
stroke-width: 8px !important; /* Set border width */
}
<!-- JavaScript class for managing general behavior -->
<!-- SVG containing the symbol -->
<svg style="display: none;">
<symbol id="redCircle" viewBox="0 0 200 200">
<circle cx="50" cy="50" r="40" fill="red" />
<script><![CDATA[
// Wait for the document to be fully loaded before setting up event listeners
document.addEventListener('DOMContentLoaded', () => {
// Add mouseover and mouseout event handlers to each <use> element
const useElements = document.querySelectorAll('[*|href="#redCircle"]');
useElements.forEach(useElement => {
const color = useElement.getAttribute('data-color') || 'red';
useElement.addEventListener('mouseover', () => {
console.log("hover");
useElement.classList.add('hovered');
});
useElement.addEventListener('mouseout', () => {
useElement.classList.remove('hovered');
});
});
});
]]></script>
</symbol>
</svg>
<!-- SVG containing two <use> references to the symbol with color properties -->
<svg id="svg-container">
<use xlink:href="#redCircle" id="use1" x="100" data-color="blue" />
<use xlink:href="#redCircle" id="use2" data-color="green" />
</svg>
If I remove the fill="red"
from the symbol it does what I want.
but I want the code to work regardless of the "fill="
attribute of the symbol.
So, here is some stuff I tried:
This CSS works, but only if I don't apply fill="red" to the symbol:
<style>
.hovered {
fill: gray; /* Apply the gray fill color */
stroke: blue; /* Add a blue border */
stroke-width: 8px; /* Set border width */
}
</style>
This CSS doesn't work at all:
<style>
.hovered circle {
fill: gray; /* Apply the gray fill color */
stroke: blue; /* Add a blue border */
stroke-width: 8px; /* Set border width */
}
</style>
This CSS doesn't work at all:
<style>
/* CSS to define the hovered class */
.hovered use circle {
fill: gray; /* Apply the gray fill color */
stroke: blue; /* Add a blue border */
stroke-width: 8px; /* Set border width */
}
</style>
and this CSS is the only one that can override the fill="red":
<style>
circle {
fill: gray; /* Apply the gray fill color */
stroke: blue; /* Add a blue border */
stroke-width: 8px; /* Set border width */
}
</style>
The Javascript code is inside the SVG for a specific reason and I like to keep it like that.
3
Answers
I have given
id="circleId"
to the red circle.I am tracking and storing it by
getElementId
underconst redC
.And modifying the colour by
redC.style.fill= "gray"
onmouseover
andredC.style.fill= "red"
onmouseout
. Works fine.I have modified your code a bit to accomodate my example, removed the JS and introduced
:hover
with CSS custom properties.As HTML data attributes currently can still only be used as stringresults from CSS
attr(..)
I think it would be best to use CSS custom properties instead.The base principle
#svg-container { color: red }
, set a default color (setscurrentColor
)#svg-container { --primary: blue; --secondary: --green /* extend at will */ }
, to set required colors. For page wide use, set them at:root
level.--dsp-color
:#use1 { --dsp-color: blue }
, a simple, direct override.#use2 { --dsp-color: var(--primary, magenta) }
, default tomagenta
when--primary
is undefined.#use3 { --dsp-color: var(--secondary, yellow) }
, default toyellow
when--secondary
is undefined.extend this list as required or use classes instead.
Instead, the above rules can also be defined in the specific HTML
<use>
as astyle="..."
e.g.<use id="use1" style="--dsp-color: blue">
, etc.--dsp-color
to finally display a circle with the required color:circle { fill: var(--dsp-color, currentColor) }
, uses the display time color variable and the current parentcolor
value. This sets the appropriate color overriding thefill
set in a<circle>
(which essentially has become redundant).The snippet is commented and should be self explanatory combined with the above. I added a few extra variables to show a more generic hover effect.
Here is a straightforward CSS approach, in which:
fill
value to the<use>
elements (via each element’sid
)<circle>
inherits thefill
value from the step above, viafill: inherit
.Working Example:
Further Reading: