CSS has features specifically to support printing, designed for user agents intended for printing, the best known of which is probably Prince. Alas, browsers aren't such user agents, and Prince is expensive ($500 for the desktop version).
So I started looking into a closely-related problem: Whether it would be possible to produce properly paginated and formatted output using the print feature of a browser (Chrome, in my case), where the user agent (the browser) outputs to the screen, not to a printer, although it is able to print the contents of the browser window. (That's not the same thing as being a user agent for printing.) As anyone who's tried it finds out, Chrome (and probably other browsers) doesn't support the CSS #page rule. That means there's no practical way to, for example, distinguish between left and right pages, but in my case that didn't matter.
All I needed was:
Paginated output, and
Precise control over placement on the printed page.
Normally, when you print a browser page exact formatting isn't important. Think of a shipping label, a boarding pass, or notes for a meeting. But, in my case, the printed page is the critical part, and the browser rendition is merely a preview. Specifically, I was trying to prepare a PDF for a photo book for uploading to MagCloud, an on-demand magazine printing service (owned by Blurb, the book-printing people).
(Many apps, like Lightroom, have book layout capabilities, but for reasons not germane to this post I couldn't use any of them.)
So my question, which I'm also going to answer is: What's a simple way to produce precise printed output from a browser?
I found that, while Chrome doesn't support #page, it does support the page-break-before style. So, to get paginated printed output, all you have to do is something like this:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
.page {
position: relative;
page-break-before: always;
width: 5.5in;
height: 8.5in;
}
.inner {
position: relative;
top: .25in;
left: .25in;
width: 5in;
height: 8in;
border: 1px solid blue;
}
</style>
</head>
<body>
<div class=page>
<div class=inner>
<p>This is page one.
</div>
</div>
<div class=page>
<div class=inner>
<p>This is page two.
</div>
</div>
</body>
</html>
Note that I'm using inches instead of pixels, thus neatly avoiding the issue of the resolution of the printed page in pixels. (It happens to be 96, but I'm not using that fact, and it might be different on different systems anyway.) Millimeters would work as well.
Here's how it looked in my browser:
I found that the built-in Windows 10 PDF print driver isn't accurate, producing pages that don't reflect the sizes I set in CSS. The free CutePDF Writer, however, is dead on, as is Mac OS X.
Here's the PDF in Acrobat Reader:
As you can see, it's perfect. All you have to do is lay out your content inside the <div class=inner> and you're set. If you want a full-page bleed, such as for a book-cover photo, put the content directly in the <div class=page>.
In my application I generated the actual HTML from a PHP program, but this static HTML illustrates the important concepts.
Related
This is a little test page. On the desktop it looks normal to me.
<html>
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<style type="text/css">
div {
background: green;
font-size: 15px;
}
</style>
</head>
<body>
<div style="width:10%">10%</div>
<div style="width:20%">20%</div>
<div style="width:30%">30%</div>
<div style="width:40%">40%</div>
<div style="width:50%">50%</div>
<div style="width:60%">60%</div>
<div style="width:70%">70%</div>
<div style="width:80%">80%</div>
<div style="width:90%">90%</div>
<div style="width:100%">100%</div>
</body>
</html>
But on my iPhone it has a strange behavior. In portrait mode everything is ok. But in landscape mode the browser calculates different font sizes although they are all set to 15px. Is there something I don't understand about font-size? I need them to look all the same.
Same thing happens on firefox, edge and chrome
I looked on the apple.com web page to see if they have the same issue. And they don't.
They use
-webkit-text-size-adjust: 100%;
and then the font size is everywhere the same.
This is not an answer, but an attempt to provide more debugging details to others looking into the issue.
I reproduced the bug in a JSFiddle to easily inspect it in the official Simulator. To inspect the page as Simulator renders it, open the page in Simulator, then open Safari on the host system and go to Settings → Advanced → enable Show Develop Menu. Following this, you can use Develop → Simulator → Show to inspect the page.
Following the above, the bug is reproducable when the phone is in landscape mode.
Inspecting the page, the styles on the element are shown as they should be. However, looking at the computed styles, we can see that a new font-size value of 21px has appeared with no inheritance.
Following the style's reference simply takes us to the 15px font-size definition.
Setting !important or other alternative configurations seem to have no effect on this value.
Outside of a better explanation, I would recommend reporting this as a bug in Safari.
To learn more and possibly find some clues, put an ID on the div and adjust your CSS accordingly. See if the result changes. This should not be needed, but playing around and trying things usually reveals some clue.
Also, what happens if you move font-size:15px; to the div element (next to the width property) ? If these alternatives work, you can see them as a way to circumvent the fault.
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
I am new to front end development- HTML/CSS. I was playing with CSS properties: "Float" and "Position:Fixed". When I run the code(given below), i got an output where the floated text and text from #static3 div tag were positioning itself in such a way that some text got hidden behind the fixed text. To make the output appear correctly, i applied the margin property for both the float text and #static3 text. For the float text the output got corrected, but for #static3 text, the whole page moves down when i apply margin property. Both are defined under seperate "div" tag(block element), then why both of them work differently.
Please help.
HTML Code:
<!DOCTYPE html>
<html>
<head>
<title>This is a layout example page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="CSS/Layyouts.css" type="text/css">
</head>
<body>
<div id="static1">This position changes</div>
<div id="static2">
This is some text thats using float attribute to be placed on right side while other text goes around and i need to make this text long to have a better look when this page is turned into a html page so better i write more
</div>
<div id="static3">This is a random text for the static example. There are many different ways you can use our services – to search for and share information, to communicate with other people or to create new content. When you share information with us, for example by creating a Google Account, we can make those services even better – to show you more relevant search results and ads, to help you connect with people or to make sharing with others quicker and easier. As you use our services, we want you to be clear how we’re using information and the ways in which you can protect your privacy.
Our Privacy Policy explains:
What information we collect and why we collect it.
How we use that information.
The choices we offer, including how to access and update information.
We’ve tried to keep it as simple as possible, but if you’re not familiar with terms like cookies, IP addresses, pixel tags and browsers, then read about these key terms first. Your privacy matters to Google so whether you are new to Google or a long-time user, please do take the time to get to know our practices – and if you have any questions consult this page.
</div>
<div id="static4">This is a random text for the static example. There are many different ways you can use our services – to search for and share information, to communicate with other people or to create new content. When you share information with us, for example by creating a Google Account, we can make those services even better – to show you more relevant search results and ads, to help you connect with people or to make sharing with others quicker and easier. As you use our services, we want you to be clear how we’re using information and the ways in which you can protect your privacy.
Our Privacy Policy explains:
What information we collect and why we collect it.
How we use that information.
The choices we offer, including how to access and update information.
We’ve tried to keep it as simple as possible, but if you’re not familiar with terms like cookies, IP addresses, pixel tags and browsers, then read about these key terms first. Your privacy matters to Google so whether you are new to Google or a long-time user, please do take the time to get to know our practices – and if you have any questions consult this page.
</div>
<div id="static5">This is a random text for the static example. There are many different ways you can use our services – to search for and share information, to communicate with other people or to create new content. When you share information with us, for example by creating a Google Account, we can make those services even better – to show you more relevant search results and ads, to help you connect with people or to make sharing with others quicker and easier. As you use our services, we want you to be clear how we’re using information and the ways in which you can protect your privacy.
Our Privacy Policy explains:
What information we collect and why we collect it.
How we use that information.
The choices we offer, including how to access and update information.
We’ve tried to keep it as simple as possible, but if you’re not familiar with terms like cookies, IP addresses, pixel tags and browsers, then read about these key terms first. Your privacy matters to Google so whether you are new to Google or a long-time user, please do take the time to get to know our practices – and if you have any questions consult this page.
</div>
<div id="static6">This is a random text for the static example. There are many different ways you can use our services – to search for and share information, to communicate with other people or to create new content. When you share information with us, for example by creating a Google Account, we can make those services even better – to show you more relevant search results and ads, to help you connect with people or to make sharing with others quicker and easier. As you use our services, we want you to be clear how we’re using information and the ways in which you can protect your privacy.
Our Privacy Policy explains:
What information we collect and why we collect it.
How we use that information.
The choices we offer, including how to access and update information.
We’ve tried to keep it as simple as possible, but if you’re not familiar with terms like cookies, IP addresses, pixel tags and browsers, then read about these key terms first. Your privacy matters to Google so whether you are new to Google or a long-time user, please do take the time to get to know our practices – and if you have any questions consult this page.
</div>
</body>
</html>
CSS code :
#static1{
position: fixed;
width: 100%;
text-align: center;
font-size: 24px;
font-family: cursive;
font-weight: bold;
text-transform: capitalize;
background-color: lightgrey;
margin: 0px;
}
#static2{
width: 200px;
float: right;
border-top: 2px black solid;
border-bottom: 2px black solid;
margin: 50px 4px 4px 4px;
padding: 2px 2px 2px 2px;
}
#static3{
margin-top: 50px;
}
FIDDLE
EDIT I think I understand what you meant to ask. The thing with the whole page moving down when you add margin to static3 is due to these things:
The static1 has position:fixed but not actual position properties ( top, right, left, bottom), so it positions itself relatively to the following element which is static2
The static2 element has a float:right property, therefore it is positioned relatively to static3 (its margin-top is calculated relatively to the top position of static3 and not the top of the body)
That way, all the elements in your page are positioned relatively to the position on the static3 div. When you add margin to that element, the other two recalculate their positions relatively to the new coordinates.
Old Answer
Not sure what you're trying to achieve, but if the goal is for the "article" to not be overlayed by its "title" (#static1), just add a top:0 property to #static1:
CSS
#static1{
top:0; // ADDED THIS LINE
position: fixed;
width: 100%;
text-align: center;
...
DEMO
The thing is you have to specify a position when you use position: fixed, or else the browser will understand that your element must not move from its original position, but will not necessarily render it in the desired position. Here, the browser understands that the static1 has to be rendered "at the top of static3 and then fixed there no matter what"
I am not aware of internal workings of CSS parser, but I can tell you that changing margin-top to padding-top in your #static3 section does solve the problem.
I've been there and that's how I solved my problem. Try for yourself.
This test image shows how wildly different Safari positions text inside a box vs Firefox (Safari 5.0.5 and Firefox 5.0.1 for Mac OS X 10.6.7). Notice how the "S" for sans-serif is butted up to the top of the box in Firefox and not Safari. The difference seem to vary depending on typeface used, where some are even consistently rendered.
I've read people saying that this is because of rounding issues between font-size and line-height (and fixed by setting smaller height than size), but I think that's disproved by my example where sans-serif/helvetica in Firefox always aligns top in the box.
To me it looks like Safari gets it more right than Firefox, i.e. text is generally more around a middle line.
Is there a good way to get them more consistent? My target is only standards-compliant browsers.
NB1: This has nothing to do with vertical-align.
NB2: I investigated a similar problem in the past with no completely satisfactory outcome.
My test code: http://jsbin.com/omaboc
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">
body {
font-size: 50px;
line-height: 1em;
}
div {
background: #b5e260;
margin-bottom: 5px;
}
</style>
</head>
<body>
<div style="font-family: sans-serif">Some text # this box</div>
<div style="font-family: serif">Some text # this box</div>
<div style="font-family: arial">Some text # this box</div>
<div style="font-family: helvetica">Some text # this box</div>
<div style="font-family: courier">Some text # this box</div>
<div style="font-family: georgia">Some text # this box</div>
</body>
</html>
Unfortunetly, there isn't a solution to this problem. Text rendering is done differently in almost every browser, and even between major browser versions it sometimes changes. In some browsers it is determined by the particular font rendering systems and settings from the OS. There have always been and always will be trade offs for one type of font rendering to another, and every one of those will change with different types of displays on different types of hardware.
Sorry, you'll have to live with non-pixel perfect fonts between browsers until there is a complete monopoly by a single browser, a single OS with no available display setting choices, a single monitor type and size, and a single video card. In other words, it's never going to match pixels perfectly as long as your site supports multiple devices, browsers, displays, etc.
(Kudos for doing your own homework and testing first though. Your question was well researched and thought before asking. I wish we could have given you a better answer after all that work.)
Have you tried using the Reset at the top of your stylesheet file??
The goal of a reset stylesheet is to reduce browser inconsistencies in things like default line heights, margins and font sizes of headings, and so on.
You can find the explanation & the code here: http://meyerweb.com/eric/tools/css/reset/
I hope this would help you!
I can get a header to print on each page, but I'm new to print margins. I thought the #page css would work, but it does not seem to affect page margins. If I set the margins on the body, it works on page one, but subsequent pages start the top margin at the default, putting the header over top of the text.
<style>
.header {
position: fixed;
top: 0;
}
#page {
size: 11in 17in;
margin-left: 1in;
margin-right: 1in;
margin-top: 1in;
margin-bottom: 1in;
}
</style>
<body>
<span class=header>This is the header</span>
This is the text of the document. (repeat until I get to page 2)
</body>
Printing support by all browsers is very poorly supported with horrendous bugs in many popular browsers that have gone unfixed for years.
The short answer is to avoid HTML/CSS printing if you need to ensure a specific layout. Use PDF, possibly dynamically generated on-demand. There's various PDF generator APIs such as iTextSharp. It's possible to print from Flash, but only if Flash is installed and working (i.e. no Flashblock, iOS).
HTML/CSS printing should be restricted to simple layouts. Form printing is a nightmare with fieldset & legend support being especially problematic (particularly on Firefox). Interestingly printing support is best on the internet explorers.
The CSS3 printing support specification hasn't been completed and is some time off.
General principles:
No backgrounds or background CSS images are supported (by default - users can change their browser settings for an intranet application). Only foreground images print.
Widths need to be fluid as page sizes vary around the planet. US Letter format is shorter and wider than A4 layout
All browsers support printing in different ways. Bugs are legion.
Test using print preview.
The accepted answer which is now 4 1/2 years old says:
"The short answer is to avoid HTML/CSS printing if you need to ensure a specific layout."
These days you may do HTML/CSS printing for comparatively simple layouts in browsers or if you use a tool like wkhtmltopdf you can go for more complex layouts. See also http://www.toccon.com/toc2013/public/schedule/detail/26714