I want to make some content available to screen readers but not visible on the page. Taking it off the page result in screen readers not announcing it, so I'm using a common hacky workaround, the sr-only class, used for instance by Bootstrap. Here's Kitty Giraudel's version:
.sr-only {
border: 0 !important;
clip: rect(1px, 1px, 1px, 1px) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
The problem is with the position: absolute rule, which necessitates a parent with position: relative. Without it, the invisible content may end up at the bottom of the page and cause the browser to add scrollbars. I don't like having to have to add that position: relative rule on top of the sr-only class. It can easily be forgotten or accidentally removed. It would be easier if adding the class was the only needed step, which seems possible by simply adding top: 0 to these rules. But I'm a little nervous tweaking with such ancient wisdom. Is there a reason why it's not commonly done this way? Am I missing a potential issue with top: 0?
Short Answer
No, do not use top: 0
Longer Answer
First the issue you linked in the comments is using a very broken (and old as far as I can tell) screen reader only class, I think it has been updated (and if not then that just reinforces my opinions on using Font Awesome! š¤£).
The screen reader class you linked is identical to the visually hidden text class I created / use (which just shows if two of us came up with the same thing it might just be right!) and should not cause the issue described as it uses clip-path: inset(50%).
clip-path: inset(50%) effectively makes the element 0px high and 0px wide, so you should never get any overflow issues because of it.
Also the scroll bar issue tends to be caused by the margin: -1px part (which you notice we aren't using in our classes), but without something to test against I cannot confirm that is the case here.
As for adding top: 0 don't do this - you are indeed wise to not mess with old wisdom.
The second you start moving the position of the element some screen readers will try and compensate for the positioning (thinking that you are a bad developer and using absolute positioning to change the order of things on the page instead of changing DOM order), resulting in strange reading orders.
I have used the class I linked for 2 years now without ever seeing any unexpected scroll bars so you should be safe.
With all that being said, if you do manage to put together a codepen / fiddle etc. that demonstrates the issue you described with the class I recommend or the class in your question then please let me know as that is something I would want to address!
Final thoughts
In the bug report you linked in the comments, do not do as the final message suggests:
Size the element such that it is 0xN, or Nx0 (e.g. "width: 0" or similar).
Make the element "display: none".
Surround the element in a 0x0 div which is also "position: absolute".
All 3 of the above options would render the text completely invisible to a screen reader user (remove the element from the accessibility tree) and completely break the point of using a screen reader only class.
Options 4 and 5 are feasible options though:
Make "viewport-router" a containing block (e.g. "position: relative" or similar).
Change the "viewport-main" to "overflow-y: hidden" or similar.
Related
For a p tag, I need the text that a screen reader reads to be different than the text contained in the p tag. I need humans to see "Jordan" and the screen reader to read "Michael Jordan." These are in a responsive grid with swiper.js. Adding title didn't work. How do I get this to work? (I can use a different HTML tag and attribute to get the same effect.)
<p role="title" title="Michael Jordan">Jordan</p>
The golden rule of accessibility is to offer as similar an experience to screen reader users as possible to non screen reader users, as such the following techniques should be used sparingly.
With that being said sometimes context etc. can be important and you need to provide extra information to screen readers.
There are numerous ways to do this:
1. aria-label
If you give an element an aria-label its contents are overridden. However this doesn't have perfect support, especially on elements such as paragraphs and divs without roles etc.
<p aria-label="Michael Jordan">Jordan</p>
Update on aria-label usage for clarity
I was not clear above as pointed out in the comments.
Hopefully this is more clear, my apologies:
Screen readers will ignore aria-label on paragraphs, divs, etc. unless they have a role that overrides their semantic meaning.
For example:
<p aria-label="Michael Jordan" role="heading">Jordan</p> will work whereas the example I gave above will not and was purely to illustrate aria-label usage.
2. Visually Hidden Text
A far more robust way of providing extra information to screen reader users is to use visually hidden text.
.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 */
}
<p><span class="visually-hidden">Michael </span>Jordan</p>
Additional important information
As far as I am aware there is no such thing as role="title" - I assume you meant something like role="heading" - at which point just use a <h1> to <h6>.
I removed the title attribute from both examples, it is essentially useless nowadays with touch devices not being able to access it, keyboard users never seeing it and it being ignored by a lot of screen readers, generally the advice would be not to use it.
Final thoughts
Also be aware, for screen reader users who navigate via mouse (i.e. people who use screen readers to assist in comprehension) neither of the above techniques are likely to change what they hear when they mouse over.
As such having the full words would be preferable if you can redesign your interface to accommodate the extra text. Doing this removes the need for any additional markup too so would be the preference.
<p>Michael Jordan</p>.
I'm trying to achieve a combination of three goals...
Determine if I should use <code><pre>...</pre></code> or <pre><code>...</code></pre>?
Make code not wrap, not create horizontal scrollbars and not overflow any parent element.
Ensure that when a visitor copies code that the white-space is maintained when they paste it in to any (competent) editor.
So far I've had the most luck with white-space: pre-wrap; however I do not want the text to wrap. If they're interested enough they'll copy-paste it for themselves. While I do not want it to wrap I also do not want it to make the element overflow outside of any parent element and I don't want the text to appear outside of it's direct parent element.
I'd be okay with a horizontal scrollbar for the code itself (pre or code element, whichever) though I'd generally prefer not to.
Just in case it's relevant I don't use any CSS frameworks or the likes, I only do a basic reset...
* {border: 0px; margin: 0px; outline: none; padding: 0px; }
I test in Firefox, then Chrome, then (actual) Opera and then maybe IE if I have sanity to spare. Thoughts please?
On number 2 and 3: Hopefully I haven't misunderstood your question--I got what I understood your goal to be working easily by by adding a fixed width and overflow:hidden to the css class.
On 1: it's working with <pre (outer)><code (inner)> so... hey.
http://jsfiddle.net/A2zhH/2/
FYI, border: gray; isn't doing anything. You need to use the format border:1px gray solid;
Goal 1 is simple: code inside pre is valid, pre inside code is not. On the other hand, pre is what matters here. You can use code inside it as a matter of principle if the content is computer code.
Goal 2 is self-contradictory as such, unless you are referring to an idea of reducing font size so that everything fits. More realistically, with regard to the statement that it is okay to have a horizontal scroll bar for the code block, use just
pre { width: 100%; overflow: auto }
This causes a horizontal scroll bar to appear for the block, instead of overflowing the content.
Goal 3 is achieved when you use normal spaces. What is copied contains spaces, and what happens to them after paste depends on the software.
I got it working to an accuracy of about 99.8% of the time using the following...
XHTML
<pre><code>/* Code here. */</code></pre>
CSS
pre {white-space: pre; width: 75vmax;}
I recently read about the "holy grail" design and read implementations for it.
I saw a solution that does something strange on the menus from the sides.
{
margin-bottom: -3200px;
padding-bottom: 32000px;
}
I understand this mechanism causes the menu to be "infinite", I also found out this trick is called bleeding.
I don't understand how it works. Can someone please explain?
EDIT:
both answers were great. Wish I could pick 2. Picked the first one answered. I found another resource that emphasizes on negative margin values which explains bleed as well.
http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/
Thanks.
Padding-bottom at that value with stretch the background of the menu down far enough that it will always be seen to take up the whole length of the page. The margin adjustment gives the ability to still position content over this stretched out menu at a position according to the design of your site. Here is an example with the properties adjusted so that you can more easily see what is happening:
http://jsfiddle.net/PVKbp/23/
.two
{
margin-bottom: -3200px;
padding-bottom: 32000px;
margin-left: 100px;
margin-right: 100px;
background-color: #aaaaaa;
}
Bleed in printing is where you create a design purposely extended over the boundaries of the canvas, to ensure that all the page is covered. It basically means that you won't get any dodgy white edges where your design didn't "fit" the document properly:
http://www.duggal.com/connect/wp-content/uploads/2010/08/bleed2.jpg
I suppose the idea of bleed is the same in this instance, whereby you're trying to cover having any potential white spaces by adding padding to the menu
CSS
The only "holy grail" I've heard of in CSS is the 3-column one? If this is the case, I would say that having padding 32000px will be needlessly resource intensive
I've never really created 100% height responsive stuff, so here's a good resource for you: Twitter Bootstrap2 100% height responsive
when inspecting elecment, I noticed the following empty span
<span class="x-tree-node-indent"></span>
in order to not having it occupy any space, I set the following style
span.x-tree-node-indent
{
left:0px;
width:0px;
height:0px;
margin:0px;
padding:0px;
}
In Chrome, I got what I wanted even without the addional styles. But in IE, I still can see a block of space over there. Any reasons? and how to fix that?
I've experienced what you're describing in IE6, 7 & 8.
You have to set the line-height to zero as well. This usually works for inline elements.
Have you tried display:none?
span.x-tree-node-indent {
display: none;
}
That should work the same everywhere but I can't check IE right now, display:none:
This value causes an element to not appear in the formatting structure (i.e., in visual media the element generates no boxes and has no effect on layout). Descendant elements do not generate any boxes either; the element and its content are removed from the formatting structure entirely. This behavior cannot be overridden by setting the 'display' property on the descendants.
Please note that a display of 'none' does not create an invisible box; it creates no box at all. [...]
Emphasis mine.
Here's a quick example if you want to check for yourself: http://jsfiddle.net/ambiguous/ZrzWz/
As noted, display: none will cause the item to take itself entirely out of the the layout. visibility: hidden will not; that is, if you had a 20px by 20px block, that block of space would continue to occupy the space even if it is hidden.
You can also set the display to block, border to none and whitespace
A few other items would be helpful to know - in order for anyone to answer this question with more than the display: none (which will work if all you are wanting to do is have it taken out of the space).
What version of IE are you referencing? In no way are the all the same.
What is the purpose of the span, if in fact you do not want it to be visible?
What doctype is your HTML? Depending, for IE there could be quirks mode involved, you may have the option of using an IE specific meta tag, telling it to render in IE7 mode etc.
For number two, if you are simply wanting to have have an indent as the name implies, then you can use the CSS text-indent: 10px (or whatever). If you have other reasons for it, there are options such as setting margins, padding on the containing area. In other words, semantically, why is this span there when there is no visibility and so on? Which then leads to have you tried other elements etc.
I can't reproduce it here. Here is my code:
span.x-tree-node-indent
{
left: 0px;
width: 0px;
height: 0px;
margin: 0px;
padding: 0px;
}
<BODY>
<P>left<SPAN class="x-tree-node-indent"></SPAN>right</P>
</BODY>
I see the one word "leftright" without any space inbetween in my IE9.
Depending upon what kind of behavior you want to achieve you may use the attributes display:none and visibility:hidden.
I am unable to get the white space at the bottom of this page to disappear. I have both min-height and height tags in body. Any suggestions? Thanks!
http://womancareolympia.webs.com/
I find it quite remarkable that out of 6 answers, none of them have mentioned the real source of the problem.
Collapsing margins on the last p inside #fw-footer is where that extra space is originating from.
A sensible fix would be to add overflow: hidden to #fw-footer (or simply add margin: 0 on the last p).
You could also just move the script inside that last p outside of the p, and then remove the p entirely; there's no need to wrap a script in a p. The first p (#fw-foottext) has margin: 0 applied, so the problem won't happen with that one.
As an aside, you've broken the fix I gave you in this question:
CSS3 gradient background with unwanted white space at bottom
You need html { height: 100% } and body { min-height: 100% }.
At the moment, you have html { height: auto } being applied, which does not work:
(This happens with a window taller than the content on the page)
The problem is how 100% height is being calculated. Two ways to deal with this.
Add 20px to the body padding-bottom
body {
padding-bottom: 20px;
}
or add a transparent border to body
body {
border: 1px solid transparent;
}
Both worked for me in firebug
In defense of this answer
Below are some comments regarding the correctness of my answer to this question. These kinds of discussions are exactly why stackoverflow is so great. Many different people have different opinions on how best to solve the problem. I've learned some incredible coding style that I would not have thought of myself. And I've been told that readers have learned something from my style from time to time. Social coding has really encouraged me to be a better programmer.
Social coding can, at times, be disturbing. I hate it when I spend 30 minutes flushing out an answer with a jsfiddle and detailed explanation only to submit and find 10 other answers all saying the same thing in less detail. And the author accepts someone else's answer. How frustrating! I think that this has happend to my fellow contributorsāin particular thirtydot.
Thirtydot's answer is completely legit. The p around the script is the culprit in this problem. Remove it and the space goes away. It also is a good answer to this question.
But why? Shouldn't the p tag's height, padding and margin be calculated into the height of the body?
And it is! If you remove the padding-bottom style that I've suggested and then set the body's background to black, you will see that the body's height includes this extra p space accurately (you see the strip at the bottom turn to black). But the gradient fails to include it when finding where to start. This is the real problem.
The two solutions that I've offered are ways to tell the browser to calculate the gradient properly. In fact, the padding-bottom could just be 1px. The value isn't important, but the setting is. It makes the browser take a look at where the body ends. Setting the border will have the same effect.
In my opinion, a padding setting of 20px looks the best for this page and that is why I answered it this way. It is addressing the problem of where the gradient starts.
Now, if I were building this page. I would have avoided wrapping the script in a p tag. But I must assume that author of the page either can't change it or has a good reason for putting it in there. I don't know what that script does. Will it write something that needs a p tag? Again, I would avoid this practice and it is fine to question its presence, but also I accept that there are cases where it must be there.
My hope in writing this "defense" is that the people who marked down this answer might consider that decision. My answer is thought out, purposeful, and relevant. The author thought so. However, in this social environment, I respect that you disagree and have a right to degrade my answer. I just hope that your choice is motivated by disagreement with my answer and not that author chose mine over yours.
I had white space at the bottom of all my websites; this is how I solved the matter:
the first and best thing you can do when you are debugging css issues like this is to add:
*{ border: 1px solid red; }
this css line puts a red box around all your css elements.
I had white space at the bottom of my page due to a faulty chrome extension which was adding the div dp_swf_engine to the bottom of my page:
<div id="dp_swf_engine" style="position: absolute; width: 1px; height: 1px;"></div>
without the red box, I would have never noticed a 1px div. I then got rid of the faulty extension, and put display:none on #dp_swf_engine as a secondary measure. (who knows when it could come back to add random white space at the bottom of my page for all my pages and apps?!)
Try setting the height of the html element to 100% as well.
html {
min-height: 100%;
overflow-y: scroll;
}
body {
min-height: 100%;
}
Reference from this answer..
This will remove the margin and padding from your page elements, since there is a paragraph with a script inside that is causing an added margin. this way you should reset it and then you can style the other elements of your page, or you could give that paragraph an id and set margin to zero only for it.
<style>
* {
margin: 0;
padding: 0;
}
</style>
Try to put this as the first style.
The problem is the background image on the html element. You appear to have set it to "null" which is not valid. Try removing that CSS rule entirely, or at least setting background-image:none
EDIT: the CSS file says it is "generated" so I don't know exactly what you will be able to edit. The problem is this line:
html {
background-color: null !important;
background-position: null !important;
background-repeat: repeat !important;
background-image: url('http://images.freewebs.com/Images/null.gif') !important;
}
I'm guessing you've put null as a value and it has set the background to a GIF called 'null'.
There is a second paragraph in your footer that contains a script. It is this that is causing the issue.
It is happening Due to:
<p><script>var _nwls=[];if(window.jQuery&&window.jQuery.find){_nwls=jQuery.find(".fw_link_newWindow");}else{if(document.getElementsByClassName){_nwls=document.getElementsByClassName("fw_link_newWindow");}else{if(document.querySelectorAll){_nwls=document.querySelectorAll(".fw_link_newWindow");}else{document.write('<scr'+'ipt src="http://static.websimages.com/static/global/js/sizzle/sizzle.min.js"><\/scr'+'ipt>');if(window.Sizzle){_nwls=Sizzle(".fw_link_newWindow");}}}}var numlinks=_nwls.length;for(var i=0;i<numlinks;i++){_nwls[i].target="_blank";}</script></p>
Remove <p></p> around the script.
(class/ID):after {
content:none;
}
Always works for me
class or ID can be for a div or even body causing the white space.
I had the same problem when parsing html to string. Removing the last <p></p> (and replacing it with an alternative if desirable, like < /br>) solved it for me.
I faced this issue because my web page was zoomed out to 90% and as I was viewing my page in responsive mode through the browser developer tools, I did not notice it right away.