I have a Gatsby project, where where I would like to use an svg as my main heading.
import Header from "../images/header.svg"
return (
<h1>
<Header/>
</h1>
)
Thers is no text in the svg (the text is made purely using rects and paths), so what do I do in terms of accessibility and SEO optimization?
Two ways to address this, visually hidden text or by adding a <title> to your SVG.
Do not use aria-label as support is not great (you will see people recommending that for SVGs, aria-label does not tend to work well on static / non-interactive elements).
Visually Hidden text (screen reader only text)
Visually hidden text is not visible on the screen but will still be read by a screen reader.
Please use the CSS class below to visually hide text, it has better compatibility and is future proofed compared to most current "screen reader only" classes as explained in this answer I gave
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<h1>
<span class="visually-hidden">Welcome To Our Site</span>
<svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
<path fill="#666" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z">
</path>
</svg>
</h1>
important: notice how I add focusable="false" as well as aria-hidden="true" to the SVG, this is to fix a bug with Internet Explorer where SVGs are focusable and to hide the SVG from screen readers. I used a youtube icon to represent your text as that was the closest SVG I had to hand!
Add a <title> element to your SVG.
The <title> element is effectively the same as alt on a normal image. Using this gives the screen reader something to announce.
Obviously you would then remove the aria-hidden="true" from it so it can be read by a screen reader!
Update after comments to include best practices for <title> and or <desc>
Thanks to the comments I realised this answer was lacking some key information on how to correctly use a <title>.
In this answer I gave I referenced a series of tests by deque which show that the most reliable method for labelling an SVG for screen readers using WAI-ARIA was to use aria-labelledby and point that to the <title> (and <desc> if you have both).
So a rough idea of how to do this is as follows:
<h1>
<svg aria-labelledby="welcome-title" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
<title id="welcome-title">Welcome To Our Site</title>
<path fill="#666" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z">
</path>
</svg>
</h1>
Which is better?
Go for visually hidden text.
It works all the way back to IE6 which predates SVG!
It also works in a text only browser (one that does not understand CSS) as it will still be displayed. It is an edge case but still a win for visually hidden text!
Related
using Big Cartel Ranger theme. I would like to have the Mailing list at the top of my social links on the footer nav, preferably with an envelope icon. The reason it has the twitter icon is because it has been input via the basic Settings within big Cartel, and I have simply modified the title from Twitter to Mailing List via the layout code, see screengrab:
[]
Please be patient! I stumble my way through any code changes through trial and *mostly *error!
I have been in touch with Big Cartel support and they were asking me to remove the Layout code that relates to twitter (pasted below) and put a simple link in, which obviously didn't work. Below is the coding that relates to the twitter link on footernav.
{% if theme.twitter_url != blank or theme.facebook_url != blank or theme.instagram_url != blank or theme.tumblr_url != blank or theme.pinterest_url != blank %}
\<nav class="footernav"aria-label="Footer social media navigation"\>
\<div class="footer-nav-title"\>Social\</div\>
<ul class="social-icons">
{% if theme.twitter_url != blank %}
<li><a href="{{ theme.twitter_url }}" title="Mailing List">\<svg xmlns="http://www.w3.org/2000/svg
" width="24" height="24" viewBox="0 0 24 24"\>\<path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.61 1.798-1.574 2.165-2.724-.95.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.18 0-5.515 2.966-4.797 6.045C7.727 8.088 4.1 6.128 1.67 3.15.38 5.36 1.003 8.256 3.195 9.722c-.806-.026-1.566-.247-2.23-.616-.053 2.28 1.582 4.415 3.95 4.89-.693.188-1.452.232-2.224.084.626 1.957 2.444 3.38 4.6 3.42-2.07 1.623-4.678 2.348-7.29 2.04 2.18 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.72 13.995-14.646.962-.695 1.797-1.562 2.457-2.55z"/\>\</svg\>\<span\>Mailing List\</span\></a></li>
{% endif %}
As above, I simply amended the title to Mailing List from Twitter.
I also tried removing the w3.org link and inputting my image link, as follows: https://www.dropbox.com/s/rtxpa88q75wpmz2/Envelope.jpg?dl=0 but the icon remained.
I also removed everything from <svg to </svg> and that removed the icon.
I then tried to input my dropbox link and removing the <path to z"/> and it didn't change anything further.
I think it requires further change in CSS. There is one section that mention social icons and it appears all are 'locked in' within their w3.org link, in which case I don't think I can change it:
.footernav ul.social-icons {
list-style: none;
margin: 0;
padding: 0;
}
.footernav ul.social-icons li {
display: block;
}
.footernav ul.social-icons li a {
color: {{ theme.accent_text_color }};
display: block;
}
.footernav ul.social-icons li a span {
display: inline-block;
margin-left: 8px;
}
.footernav ul.social-icons li a svg {
\-webkit-transition: 0.1s ease-in-out;
transition: 0.1s ease-in-out;
display: inline-block;
fill: {{ theme.accent_text_color }};
height: 16px;
opacity: 0.6;
position: relative;
top: 3px;
width: 16px;
}
.footernav ul.social-icons li a:hover svg {
opacity: 1;
}
Any help appreciated, thanks in advance!
This one took me a while to figure out when I was editing my own icons, but it's easy to change! For this particular theme, there are two Twitter code bits you'll want to change under Layout.
So to switch the icons associated with the Twitter link, you'll want to take out this SVG code on or around lines 147 and 252 (depending on if you've implemented more code) of your Layout:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.61 1.798-1.574 2.165-2.724-.95.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.18 0-5.515 2.966-4.797 6.045C7.727 8.088 4.1 6.128 1.67 3.15.38 5.36 1.003 8.256 3.195 9.722c-.806-.026-1.566-.247-2.23-.616-.053 2.28 1.582 4.415 3.95 4.89-.693.188-1.452.232-2.224.084.626 1.957 2.444 3.38 4.6 3.42-2.07 1.623-4.678 2.348-7.29 2.04 2.18 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.72 13.995-14.646.962-.695 1.797-1.562 2.457-2.55z"/></svg>
Be sure to leave the < a > tags around them! Now, you'll want to replace those SVG code bits with the following in both places, to which I used a free envelope icon from Font Awesome:
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.2.1 by #fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z"/></svg>
This should get you the results you're wanting with that envelope on both desktop and mobile. :) Let me know if this works for you!
I don't know how to really explain this but how can I center align this logo
http://jsfiddle.net/fa7w3h99/3/
I have tried the following but it didnt seem to work as intended.
.center-logo {
display: block;
margin: auto;
}
You will have to change the width, height, and viewbox attributes of your svg.
Here I'd say it should be :
width="135px" height="135px" viewBox="0 0 135 135"
jsfiddle
I'm creating a dom structure which includes an SVG element:
<div data-bind="with: searchable_select.f0000001" style="verticalAlign: top">
<input data-bind="value: select_filter_value, valueUpdate: 'afterkeydown', event: { change: change_filter_, blur: blur_filter_ }" style="display: none">
<div>
<select data-bind="options: select_list, value: working_value, event: { change: change_selector_ }, optionsText: 'label', optionsValue: 'value'" style="display: inline-block; maxWidth: 150px">
<option value="person_full_name_asc">Member Full Name (A-Z)</option>
<option value="person_full_name_desc">Member Full Name (Z-A)</option>
</select>
<svg style="display: inline-block; verticalAlign: middle" width="18" height="18" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle cx="6" cy="6" r="5" fill="#AAAAAA" stroke="#000000" stroke-width="2"></circle>
<path fill="#AAAAAA" stroke="#000000" stroke-width="2" d="M10,10 L17,17"></path>
</g>
</svg>
</div>
</div>
The svg element does not actually display. When I find the svg element in Chrome developer tools, both width and height show as zero.
I've tried removing the style attribute. I've tried setting the width and height in the style attribute.
I've copied the svg to a separate HTML file:
<html>
<head><title>maggen</title></head>
<body>
<svg style="display: inline-block; verticalAlign: middle" width="18" height="18" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle cx="6" cy="6" r="5" fill="#AAAAAA" stroke="#000000" stroke-width="2"></circle>
<path fill="#AAAAAA" stroke="#000000" stroke-width="2" d="M10,10 L17,17"></path>
</g>
</svg>
</body>
</html>
Where it displays fine.
If I wrap the svg element in a div, the svg element shows up. In fact, if I edit the HTML in Chrome developer tools it will show up.
So, yeah, why? I've done a search on Google for this, but either it isn't there or (more likely) my Google Fu is not up to the task. I mean, sure, I can wrap it in a div - and maybe that's the right thing to do - but I'd rather not because then I'd need to wrap other stuff in divs and the dom will start to get cluttered.
EDIT: On a hunch I tried editing viewport attribute into the SVG element in Chrome tools. Voila! The element is visible! Expect when I included the viewport attribute when creating the document, it's not visible. So I tried just adding a random attribute in Chrome tools to the SVG element. Voila! The Element is visible! So, I thought, the problem is specific to Chrome and tried running it in Firefox...
...where the element doesn't show up.
EDIT: Great, so wrapping it in a div is not guaranteed to make it show up. But doing an "edit as HTML" in Chrome developer tools does make it show up.
EDIT: Well, I've gotten it to work correctly and, yes, it turns out to be a function of the Javascript creating the DOM elements. There's a lot of stuff in the code, but I can boil it down to this:
This code works (createElement creates a tag and sets attributes based on passed in parameters):
var div = this.createElement(
'div',
element_name + '_div',
null, style_options, null, null
);
div.innerHTML = [
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width=' + width + ' height=' + height + '>',
svg_xml.join(''),
'</svg>'
].join('');
if (parent) parent.appendChild(div);
return div;
This code doesn't:
var svg = this.createElement('svg', element_name, null, style_options, classlist, {
viewport: '0 0 ' + width + ' ' + height,
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
width: width,
height: height
});
svg.innerHTML = svg_xml.join('');
if (parent) parent.appendChild(svg);
return svg;
So, sure, I've got something working now, but I don't understand why. Or more to the point, I don't understand why one way works and the other doesn't. I have a couple of guesses, but they are just wild guesses, really.
"I've got something working now, but I don't understand why."
The issue is that the methods you were using do not create an SVG element in the SVG namespace. The xmlns attribute only affects the behaviour of an XML parser, not of DOM methods.
I'm not sure which library you're using for the this.createElement() method with multiple parameters. However, I suspect it probably starts by calling the basic document.createElement(tagName) method. This is what MDN says about the standard DOM createElement method:
In an HTML document creates the specified HTML element or HTMLUnknownElement if the element is not known. ... In other documents creates an element with a null namespaceURI.
In other words, because you're (presumably, indirectly) calling createElement on an HTML document, it always creates an HTML element. An HTML element with tag name "svg" is just treated as an unknown span-type element.
In contrast, using div.innerHTML to pass a markup string creates the SVG element correctly because it invokes the HTML5 parser to figure out what type of element to create. The namespace is determined using the same rules as when parsing markup from a file. Editing the HTML in the Chrome developer tools has the same effect.
Sidenote: Avoid calling .innerHTML on an SVG element. Some browsers support it, but it's not part of the specs. You're not getting an error because your svg variable is actually an instance of HTMLUnknownElement. Passing SVG code to the innerHTML method of a parent <div> usually works, although there are some bugs with SMIL animation. As #Robert Longson says in the comments, you can use the DOMParser object to parse either HTML or XML code into a document.
The other way to dynamically create an SVG element is to use document.createElementNS(namespaceURI, tagName). You'll also have to use this method to create all the child elements of the SVG. Once they are created, you may be able to set attributes, styles, and classes using your library methods. (But you haven't specified what library you're using, so I'm not sure.)
I have a bunch of line elements created with D3 but the strange thing is that they're appearing in the DOM and when I mouseover them I see it being highlighted but there isn't anything there, everything is just blank. The code somewhat looks like this and the CSS has some weird webkit-transform-origin stuff. Does anyone know what is wrong? (screenshot of issue: http://imgur.com/HRE01Gd)
<div>
<svg width="1000" height="700">
<line x1="420" y1="470" x2="394.9078930250818" y2="369.0723716341295" id="id-1" style="stroke- width: 10px; color: red;"></line>
</svg>
</div>
-webkit-transform-origin-x: 0px;
-webkit-transform-origin-y: 0px;
-webkit-transform-origin-z: initial;
color doesn't do anything. Set stroke instead. At the moment, all of your lines are getting rendered with no stroke at all, which makes them invisible.
You need to change color to stroke. For instance:
<line x1="420" y1="470" x2="394.9078930250818" y2="369.0723716341295" id="id-1" style="stroke-width: 10px; stroke: red;"></line>
I had same problem. Tried to set stroke-width - did not help. Fixed it with correct x position of the element.
Lets say I have some markup like this:
<html>
<head>
<style type="text/css">
#container
{
margin: 0 auto;
width: 900px;
background: green;
}
</style>
</head>
<body>
<div id="container">
</div>
</body>
</html>
Imagine "container" is filled with hundreds of a's for testing purposes of padding.
Now, what I want to do is to make an area of whitespace between the edges of "container" and its content on the left and right hand sides. So I add:
padding-left: 50px;
padding-right: 50px;
Now from what I (thought) I understood, this would mean that if 100 a's fitted per line before, only 80 or so would fit now. In other words, "container" would remain the same width but grow downwards.
However, what I am seeing is that the size of "container" is increasing horizontally and not vertically.
How can I get "container" to grow down vertically and stay the same width horizontally?
You need to change the width to 800px and then add your padding. Padding is additive to the width.
W------W - original width
PW------WP - original width plus padding either side
PW----WP - smaller width plus padding either side
Box model courtesy of Can Berk Güder
What garry said, If youre using Chrome or Firebug plugin for Firefox you can right click and "inspect element" and see a visual representation of how your elemenent is being sized, really helps in these situations.
The affects of adding padding or margin to an element depend entirely on the browser you're viewing the page in. Padding and margin SHOULD be additive as Garry says but that's not the case with IE6 so you'll need to do some research around browser differences and how you can accommodate them in your style rules.
From what it looks like your doing you just want a padding to be applied to the whole page. You could do that by directly referencing body in your CSS. so you'll have -
body
{
padding:0 50 0 50;
}
You could also add a margin to anything inside the div:
<style type="text/css">
#container
{
margin: 0 auto;
width: 900px;
background: green;
}
#container *
{
margin-left: 50px;
margin-right: 50px;
}
</style>