Please consider the following HTML markup:
<label class="required" for="email-address">
Email Address
<span class="audible">Required</span>
</label>
<input type="text" id="email-address" placeholder="Company#address.com">
Along with that I have the following CSS:
.required:after {
color: red
content: "*";
/* ... */
}
When I focus the field a screen reader will read out: Email Address required "star". I'd like to use CSS only to display a visual *, but I don't want that read by screen readers. Is this possible?
Or is this scenario common enough that screen readers and users would ignore the star or adjust the settings. I.e., is this not a real problem?
Try this, it targets screen readers with a media query and hides the star
#media reader, speech, aural {
.required:after {
display: none;
visibility: hidden;
}
}
Update:
As the support for my initial solution doesn't seem to be that good I have thought of a alternative. It occurred to me that the only way to ensure that its not read by a screen reader (w/o extra markup) would be to have no asterisk at all! However you could add a image with css to look like a asterisk like so:
.required:after {
content:'';
display: inline-block;
width: .5em;
height: .5em;
background-image: url(http://upload.wikimedia.org/wikipedia/commons/b/b5/Asterisk.svg);
background-size: .5em .5em;
vertical-align: top;
margin-left: .15em;
margin-top: .1em;
}
http://jsfiddle.net/3a1dvdag/
Gonna throw this out here as there's no final answer highlighted and it's a much discussed topic.
The above solution given by #Sam will be in the near future the best option to go for. No browsers thus far that have the #media aural, speech media query so, if you provide it, it will only work in the near future.
Is there any other way to hide pseudo elements from screen readers?
Yes, with limits. You can use the "private use Unicode character set".
Because the characters are private use, screen readers cannot pronounce them and therefore ignore the character.
If that's not an option try to stick to <span> or <i> elements with aria-hidden="true" on them. It's not as clean as pseudo elements, but at least you have full control of the content.
<button type="button">
<span class="i i-arrow-down" aria-hidden="true">Label
</button>
There's this syntax where one can set the alt text for pseudo elements using slash as delimiter. We can leave it blank to indicate the element should be ignored (the same way it is usually done with img tags), like this:
.required:after {
color: red
content: "*" / "";
......
}
This source indicates there was an 'okay' browser support on 2020. I've tested in Chrome with VoiceOver on MacOS and it works now (as opposed to what the table indicates), so hopefully support may already be very good by now.
https://a11ysupport.io/tests/tech__css__css_generated_content_alt
Right now I think there only exists either workarounds like using a combination of HTML elements and aria-hidden, or limited support from browsers that implement the CSS3 speech module.
Note that this module is still at Candidate Recommandation level, but should provide a more accurate control on what should be read aloud or not.
If browser support was perfect, a good answer would be:
Use CSS3 speech module.
But yeah, this is the Web, and browser support isn't perfect, so I'd recommend using some combination of span with aria-hidden="true" even 4 years after this question was asked.
But one should know that although the aria-hidden property indeed prevents the element content from being read, it also hides its presence to the user. The difference is subtle, but the speak property will not hide the element presence by mentioning it when saying how many children belong to an element.
For instance, let's consider this code:
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>What a beautiful day!</title>
<style type="text/css">
body {
counter-reset: headers;
}
h2::before {
counter-increment: headers;
content: counter(headers, upper-roman);
speak: none;
}
</style>
</head>
<body>
<h2>Early morning</h2>
<h2>Lunch</h2>
<h2>Before dinner</h2>
</body>
</html>
And this is what Voice Over reads for the Lunch element, on a supporting web browser (Firefox 59 here):
It counts the speak: none; element in (pseudo-elements count for one), but doesn't read it alound.
Using aria-hidden leads the element not to be counted at all.
I haven't tried other screen readers, and your mileage may vary.
If you use a separate span for your icon you could apply an aria hidden tag to prevent screenreaders from reading it. I'm not sure what the support is for this though.
<label class="required" for="email-address">Email Address
<span class="icon" aria-hidden="true"></span>
<span class="audible">Required</span> </label>
<input type="text" id="email-address" placeholder="Company#address.com">
More info in the W3C spec
Related
Today I found out something weird regarding the way CSS works.
Basically I tried to apply some styles to head, title and script.
I was buffled to find out that this thing worked, so I'm obviously trying to find out why would such a thing be possible.
I got some code going on: here.
I even tried this thing on a local project and it behaves the same, so it's not something related to plunker.
Any clues?
HTML Markup:
<head>
<title>Am I styled?</title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<script>console.log("Stylish!");</script>
</head>
CSS:
title {
color: red;
display: block;
font-size: 30px;
}
head {
display: block;
border: 3px solid black;
}
script {
display: block;
color: green;
}
It is possible because there is no good reason for it to be impossible.
To make it impossible there would have to be special casing to treat the elements differently. That means more work and more complexity (and thus more opportunity for bugs) both in the browsers that handle HTML and CSS and in the HTML and CSS specifications.
It is possible because browsers have been developed to process HTML elements more uniformly. For example, the “unusual styling” does not work on IE 8 and older. In modern browsers, rendering is more systematically based on CSS concepts; all elements have all CSS properties, and the value of the display property controls the overall way of rendering the element. For head and possibly for its children, the default is display: none. As you’ve seen, this can be overridden.
Marginally, the motivation behind this may also have included the idea that authors could make some use of styling elements that are normally invisible. For example, a page that discusses CSS might wish to show its own style settings, as set in a style element, simply by making that element visible and suitably formatted, e.g.style { display: block; white-space: pre }`.
I'll be completing a website soon for my university (in fact, it's mostly finished now other than some mild tweaking) and I'd like to add a hidden thank-you to some bloggers who helped, and the stack overflow community which was a huge help. Right now, I've got a text section which is hidden this way:
<font style="font-size:0px"> - text </font>
But I feel like there's probably a better way. Is there?
This will keep its space, but not show anything;
opacity: 0.0;
This will hide the object fully, plus its (reserved) space;
display: none;
<div style="display:none;">CREDITS_HERE</div>
you can use css property to hide style="display:none;"
<div style="display:none;">CREDITS_HERE</div>
You said that you can’t use HTML comments because the CMS filters them out. So I assume that you really want to hide this content and you don’t need to display it ever.
In that case, you shouldn’t use CSS (only), as you’d only play on the presentation level, not affecting the content level. Your content should also be hidden for user-agents ignoring the CSS (people using text browsers, feed readers, screen readers; bots; etc.).
In HTML5 there is the global hidden attribute:
When specified on an element, it indicates that the element is not yet, or is no longer, directly relevant to the page's current state, or that it is being used to declare content to be reused by other parts of the page as opposed to being directly accessed by the user. User agents should not render elements that have the hidden attribute specified.
Example (using the small element here, because it’s an "attribution"):
<small hidden>Thanks to John Doe for this idea.</small>
As a fallback (for user-agents that don’t know the hidden attribute), you can specify in your CSS:
[hidden] {display:none;}
An general element for plain text could be the script element used as "data block":
<script type="text/plain" hidden>
Thanks to John Doe for this idea.
</script>
Alternatively, you could also use data-* attributes on existing elements (resp. on new div elements if you want to group some elements for the attribution):
<p data-attribution="Thanks to John Doe for this idea!">This is some visible example content …</p>
display: none or visibility: hidden.
Here are two ways you can achieve this
You can display none or have a opacity none...But if you want the opacity to be cross browser compatible you would have to add this to your css
/* IE 8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
/* IE 5-7 */
filter: alpha(opacity=50);
/* Netscape */
-moz-opacity: 0.5;
/* Safari 1.x */
-khtml-opacity: 0.5;
/* Good browsers */
opacity: 0.5;
http://codepen.io/anon/pen/Krkfj
Not sure if this was what you were asking for, but I was personally trying to 'hide' some info in my html so that if someone inspected it, they would see the text in the source code.
It turns out that you can add ANY attribute, and so long as it isn't understood by the browser, it will just be left buried in the tag. My code was an easter egg: For people who couldn't afford to do the Makers Academy course, I basically encouraged them to inspect the element, where they would be given a secret URL where they could apply for a special, cut-price course (it's in haml, but it's the same idea in HTML):
.entry
%h2 I can't afford to do the course... What should I do?
%p{:url_you_should_visit => 'http://ronin.makersacademy.com'} Inspect and you shall find.
Or in html:
<p url_you_should_visit="http://ronin.makersacademy.com">Inspect and you shall find.</p>
Because 'url' is not a recognised html attribute, it makes no difference but is still discoverable. You could do the same with anything you wanted. You could have an attribute (in html) like:
<p thanks="Thanks to all the bloggers that helped me"> Some text </p>
And they'll be able to find your little easter egg if they want it... Hope that helps - it certainly helped me :)
use css property style="display:none" or style=visibility:hidden"
Use the CSS property visibility and set it to hidden.
You can see more here.
Let's say I have a basic webpage:
<LABEL ID="THE_LABEL" FOR="THE_CHECKBOX"><INPUT TYPE=checkbox ID="THE_CHECKBOX"/> Blue when checked!</LABEL>
Now let's say that I want the label text to be red when it's unchecked and blue when it's checked. How would I do this? I want something as basic as the following. Here, I use a hypothetical operator "<", which would mean "has the child", but of course it won't work, as there's no such operator:
#THE_LABEL{
color:red;
}
#THE_LABEL < #THE_CHECKBOX[checked]{
color:blue;
}
Everything but the theoretical "<" is valid CSS, which makes me wonder if there's a real way to achieve this behavior. Does anyone know of a valid CSS 3 (or lower version) way to style a label based on the state of its checkbox, without using JavaScript?
You shouldn't be putting the input field within the label.
Since the contents of the label appear after the checkbox, just make your HTML this way:
<INPUT TYPE=checkbox ID="THE_CHECKBOX"/>
<LABEL ID="THE_LABEL" FOR="THE_CHECKBOX">Blue when checked!</LABEL>
And then use this CSS:
#THE_LABEL {
color: red;
}
#THE_CHECKBOX:checked + #THE_LABEL {
color: blue;
}
Live demo
The + is a sibling selector. It is not supported by IE8 and below.
Sorry, see:
Is there a CSS parent selector? and Complex CSS selector for parent of active child
for more discussion about this topic, but it doesn't seem to be possible.
I believe this will work in CSS4, but that's really just theoretical for now:
#THE_LABEL{
color:red;
}
#THE_LABEL /for/ :checked {
color:blue;
}
JSFiddle test
Browser Support
I come back to this every couple months just to check. Here's the support status for modern versions of the following layout engines:
WebKit: NO (Safari, iOS web views)
Blink: NO (Chrome, Chromium-based browsers, many open-source projects, Android web views)
Gecko: NO (Firefox, many open-source projects)
Trident: NO (IE, Windows web views, Steam)
EdgeHTML: NO (Microsoft Edge)
The CSS has selector is slowly being implemented across browsers.
Currently, according to caniuse.com, it has 56.19% support globally.
Using this selector you can achieve what your original question asked for: styling a label based on the checked state of a nested checkbox.
The codepen showing the example is here and the html used in the example is below. Note, this will work in Chromium browsers but not in Firefox at the moment (see the canIUse page referenced above for more on supported browsers).
<style>
label {
color: red;
}
label:has(> input[type='checkbox']:checked) {
color: blue;
}
</style>
<label>
Me blue when checked.
<input type="checkbox">
</label>
I'm designing a html page with strict doctype and there's a form element in my page.
What I want to do is to change background-color of inputbox when mouse touches my form. I've done this with css :hover selector on form tag, but problem is that IE only understands hover on "a" tag!
I've googled my problem and what I found is to:
using an htc file;
using javascript to create a hover class on elements;
creating a big "a" tag and put all elements inside it;
but I don't want to do any of these solutions!
Isn't there any better way to fix this problem in IE?
My HTML Code:
<form id="footer-search-form" title="Search" action="#action">
<fieldset>
<input type="text" class="footer-search-input" id="q" name="Search"></input>
<input type="button" class="footer-search-button" title="Search" value="Search"></input>
</fieldset>
</form>
My CSS Code:
#footer-search-form:hover .footer-search-button { background-color: #fff; }
#footer-search-form:hover .footer-search-input { background-color: #fff; }
Update: and after hours of searching I did it by using js:
onmouseover="this.setAttribute(document.all?'className':'class','footer-search-hovered');" onmouseout="this.removeAttribute(document.all?'className':'class','footer-search-hovered');"
and
.footer-search-hovered .footer-search-input, .footer-search-hovered .footer-search-button { background-color: #fff !important; } /* For IE6 compatibility */
I hate it, but it seems that there's no better way...
You're really only going to run into trouble if your users are using IE6. The majority of web developers nowadays don't even bother providing support for such an old browser, so I wouldn't worry about it.
IE has supported :hover on any element since IE8 (or even IE7? I don't remember), which has been released for over three years. Admittedly far too many people still use IE6 (mostly because IE doesn't have an auto-updater - it really needs one), but for something as simple as this aesthetic effect you really don't need to worry about support in old relics.
On the page there are links displayed with CSS as buttons:
HTML:
<a class="button" href="#">Button</a>
CSS:
a.button {
display: block;
position: relative;
width: 50px;
height: 50px;
background-color: $00f;
}
a.button:hover {
background-color: $f00;
}
I have some main concerns:
The href value is encrypted, thus will appear messy and ugly when the address shows in the browser when the user hovers over the link:
http://mysite.com/shjfgkh53hhsfd9ah390503hh35323j5hj35909ufudufdjj3
Also the href value will become significantly longer because I can't transfer POST parameters (everything's done by GET).
I could however, use this:
HTML:
<input type="button" class="button" href="#" />
And then set the bg in CSS. I'm just not sure whether using pseudo classes like :hover is correct and standards compliant here. I personally thought :hover, :active, :visited etc were meant for links (i.e. a tags).
Clarifying this would really help me out a lot. Thanks!
They may not work correctly IE6, but all current browsers support this, and the spec doesn't forbid it: See here for the spec.
What matters is what's supported by browsers. Honestly, if they're using IE6 and something doesn't work...in this case it's not a breaking lack of functionality, your site works just fine even without. I'd say you're perfectly in the clear here.