Interactive Text
Because SVG text is part of the DOM, in an interactive web document, it can be updated or restyled in response to user interaction.
In the simplest version, the CSS :hover
class can be used to show and hide text labels, thereby reducing the amount of visual clutter as the user explores the image.
In Example 7-3, in the book, we added text labels to a product photograph of bicycle. Then, we showed how media queries could automatically increase the size of those labels when the graphic is scaled down.
With hover styles, we can hide and show those labels as the user explores the graphic, helping to focus attention on the individual parts.
We make the connection with invisible shapes that outline the features in the photograph that correspond to each label, turning the SVG into a simple image map. When the CSS registers a :hover
on any of the shapes, the matching text element is revealed.
To keep things accessible, we’re only going to hide the labels if a hover-effect is detected somewhere on the SVG. Without mouse movement or active tap interaction, all the labels will display.
Tip
If the interaction was essential, we could make the elements keyboard-focusable and use the :focus
pseudoclass, but too many tab stops can be an accessibility problem, too. So keyboard users will just see all the labels at once.
Example 7-X1 provides the complete code; Figure 7-X1 shows each label revealed in turn.
Example 7-X1. Making SVG text labels interactive on mouseover
SVG markup:
<svg
xmlns=
"http://www.w3.org/2000/svg"
xml:lang=
"en"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"1000"
height=
"586"
viewBox=
"0 0 1000 586"
id=
"lynskey"
>
<title
>
Lynskey 2017 Vialé Technical Details
</title>
<style
>
/* see below */
</style>
<image
width=
"100%"
height=
"100%"
xlink:href=
"viale.jpg"
/>
<g
>
<circle
class=
"target"
cx=
"770"
cy=
"400"
r=
"172"
/>
<circle
class=
"target"
cx=
"220"
cy=
"380"
r=
"172"
/>
<text
x=
"360"
y=
"520"
>
DTSwiss TK540/X.9 Wheelset
</text>
</g>
<g
>
<polygon
class=
"target"
points=
"250,25 443,25 443,60 357,101 260,65"
/>
<text
x=
"80"
y=
"120"
>
Selle Italia X1 Flow Saddle
</text>
</g>
<g
>
<polygon
class=
"target"
points=
"646,105 367,130 245,350 283,409 390,434 413,379 456,370 500,400 677,207 684,229 700,217 669,120"
/>
<text
x=
"420"
y=
"200"
>
Titanium frame
</text>
</g>
<g
>
<circle
class=
"target"
cx=
"225"
cy=
"400"
r=
"55"
/>
<polygon
class=
"target"
points=
"210,400 230,480 260,480 280,390"
/>
<text
x=
"80"
y=
"570"
>
SRAM Apex rear dérailleur
</text>
</g>
</svg>
-
Each
<text>
label is now part of a group (<g>
element) that also contains the shapes that outline the labelled regions of the photograph. -
The mouse-target elements include a mix of
<circle>
and<polygon>
elements. Thetarget
class will be used to make the elements invisible, so it doesn’t matter if the shapes are only rough approximations for the photographic regions. -
Although they won’t be displayed, the order of the shapes still matters: the dérailleur (gear-shift) region overlaps one of the wheels, but it is later in the document and therefore “on top” as far as mouse events are concerned.
CSS styles:
svg
text
{
font
:
20px
sans-serif
;
fill
:
darkBlue
;
transition
:
font-size
0.5s
,
opacity
0.3s
;
}
@media
(
max-width
:
600px
)
,
(
max-height
:
342px
)
{
svg
text
{
font-size
:
28px
;
}
}
@media
(
max-width
:
400px
)
,
(
max-height
:
235px
)
{
svg
text
{
font-size
:
36px
;
}
}
.target
{
fill
:
none
;
pointer-events
:
visibleFill
;
}
svg
:hover
g
:not
(
:hover
)
text
{
opacity
:
0
;
}
-
We previously added the
transition
property to smooth outfont-size
changes from the media queries. An additional transition has been added for theopacity
property of the<text>
elements, so that the labels fade in and out neatly. -
The media queries for adjusting
font-size
are as described in “Responsive Text Scaling” in Chapter 7 of the book. -
The shapes with the
target
class aren’t painted (fill
isnone
instead of the default black) but they do respond to mouse-pointer events. ThevisibleFill
value for thepointer-events
property means that the fill region of the shape is active unless the shape is explicitly hidden with thevisibility
property, regardless of whether or not it is actually painted. (We discusspointer-events
in more detail in Chapter 18.) -
When the SVG is hovered by a mouse pointer, the text elements are transparent (
opacity: 0
), unless they are inside a group that is also receiving the mouse hover event. Theopacity
property is used, instead ofvisibility
ordisplay
, because it can be smoothly transitioned, and because it doesn’t affect pointer events on the text itself.
Interactive effects don’t work in an SVG used as an image. Mouse events on an <img>
element are handled by the parent document, not passed to the SVG.
However, as we discussed in the book, there are already many other reasons why this example shouldn’t be used in an image: the text would be inaccessible, and the external photograph file would not load! So this approach is for <object>
or (with adjusted media queries) inline SVG, only.