Вадим Макишвили, WSD декабрь 2013
...и это ещё не все
чистая
удобная
подробная
полная
наглядная
21х29cm
15х15cm
15х10cm
12х12cm
3х3cm
15х15cm
15х12cm
15х15cm
20 х 27cm
... Quirks again?
1998
2012
Quirks Mode<table height='100%'>
...
</table>
td.map {
height: 100%
}
Javascript?
if (page.orientation === 'landscape') {
// do something
}
if (page.size.width === '210mm') {
// do something
}
@media print and (orientation:landscape) {
// do something
}
/* Обнулить поля */
@page {
margin: 0
}
/* Обнулить поля */
@page {
margin: 0
}
/* Обнулить поля */
@page {
margin: 0
}
Не работает?
/* Изменить поля */
@page {
margin: 1cm
}
Заработало!
/* Изменить поля */
@page {
margin: 1cm
}
Точка отсчёта -
дефолтные отступы,
а не край листа
/* Принудительно задать ориентацию */
@page {
size: landscape
}
/* Группировка свойств */
@page myName {
font-size: 18px
padding: 10px
}
div {
page: myName
}
@page chromePage { margin: 0 }
body.chrome { page: chromePage }
@page operaPage { margin: 5mm }
body.opera { page: operaPage }
@page { margin: 0 }
null
@page operaPage { margin: 5mm }
body.opera { page: operaPage }
@page { margin: 0 }
null
@-moz-document regexp('*') {
@page {
margin-top: 1cm;
margin-bottom: 1cm;
}
}
@media print and (orientation:portrait) {
/* стили только для портрета */
}
@media print and (orientation:landscape) {
/* стили только для альбома */
}
table, td.map {
height: 100%
}
div {
display: table-cell
}
.map {
height: 100%
}
min-height
и max-height
overflow:hidden
внутри ячейкиdiv {
position: absolute
left: 0
right: 0
}
.head {
top: 0
height: 100px
}
.map {
top: 100px
bottom: 100px
}
.foot {
bottom: 0
height: 100px
}
page-break-before
.map {
height: 100%
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
body {
width: 900px
}
@media print {
body {
width: auto /* переопределяю */
padding: 5mm
}
}
@media all {
body { font-size: 16px }
}
@media screen {
body { width: 900px }
}
@media print {
body { padding: 5mm }
}
@media screen {
body { width: 900px }
}
@media print {
body { padding: 5mm }
}
@media print and (orientation:landscape){
body { height: 210mm }
}
<meta http-equiv='X-UA-Compatible' content='IE=EmulateIE7'>
<!--[if gt IE 7]><!-->
<link href='page.css'>
<!--<![endif]-->
<!--[if lt IE 8]>
<link href='page.ie.css'>
<![endif]-->
<link rel='stylesheet' href='page.screen.css' media='screen'>
<link rel='stylesheet' href='page.print.css' media='print'>
<link rel='stylesheet' href='page.print.portrait.css' media='print and (orientation:portrait)'>
<link rel='stylesheet' href='page.print.landscape.css' media='print and (orientation:landscape)'>
<meta ... content='IE=EmulateIE7'>
<meta ... content='IE=EmulateIE7, IE=edge'>
<div class='view'>
<img class='map' src='map.png'>
</div>
.view {
position: relative
overflow: hidden
width: 200px; height: 200px
}
.map {
position: absolute
top: 50%; left: 50%
width: 1000px; height: 1000px
margin: -500px 0 0 -500px
}
<div class='view'>
<img class='map' src='map.png'>
</div>
.view {
position: relative
overflow: hidden
width: 200px; height: 200px
}
.map {
position: absolute
top: 50%; left: 50%
width: 1000px; height: 1000px
margin: -500px 0 0 -500px
}
overflow: hidden
<div class='view'>
<img class='map' src='map.png'>
</div>
.view {
position: relative
overflow: hidden
width: 200px; height: 200px
}
.map {
position: absolute
top: 50%; left: 50%
width: 1000px; height: 1000px
margin: -500px 0 0 -500px
}
+ display: inline-block
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
+ <div class='opacity-hack'></div>
.opacity-hack {
position: absolute
background: red
opacity: 0.3
}
.map {
height: 100%
}
.head, .foot {
position: absolute
left: 0
right: 0
}
.head {
top: 0
}
.foot {
bottom: 0
}
<div class='opacity-hack'></div>
.opacity-hack {
position: absolute
opacity: 0
}
(function () {
var ua = navigator.userAgent;
var browser = jQuery.browser;
var browserName;
switch (true) {
case Boolean(browser.opera):
browserName = 'opera'; break;
case Boolean(ua.indexOf('Safari') !== -1):
browserName = 'safari'; break;
...
}
if (browserName) {
document.documentElement.className += (' ' + browserName);
}
}());
<html class='opera'>
...
</html>
html, body {
height: 100%
}
.map {
width: 100%
height: 100%
}
html, body {
height: 100%
}
.map {
width: 100%
height: 100%
}
html, body {
height: 100%
}
.map {
width: 100%
height: 100%
}
@media print {
@page { margin: 5mm }
html.chrome { height: 267mm }
html.safari { height: 247mm }
}
@media print and (orientation:landscape) {
html.chrome { height: 187mm }
html.safari { height: 167mm }
}
/* Обнулить поля */
@page {
margin: 0
}
/* Обнулить поля */
@page {
margin: 0
}
/* Обнулить поля */
@page {
margin: 0
}
Молодец!
/* Обнулить поля */
@page {
margin: 0
}
Молодец!
border
outline
if (window.matchMedia(' (min-width: 400px) ').matches) {
// do something
}
if (page.orientation === 'landscape') {
// do something
}
if (window.matchMedia('print and (orientation: landscape)').matches) {
// do something
}
if (window.matchMedia('print').matches) {
// do something
}
if (window.matchMedia('print and (orientation: landscape)').matches) {
// do something
}
.footer {
position: absolute
bottom: 0
}
.footer and (min-height: 86px) {
position: static
}
if (footerHeight > 86) {
footer.addClass('on-next-page');
}
/* Больше 86px — отправляется на второй лист */
.footer.on-next-page {
position: static
}
@media print and (orientation: landscape) {
.footer and (min-height: 160px) { position: static }
}
@media print and (orientation: portrait) {
.footer and (min-height: 240px) { position: static }
}
if (footerHeight > 160) {
footer.addClass('on-next-page_for-landscape');
}
if (footerHeight > 240) {
footer.addClass('on-next-page_for-portrait');
}
<!-- Подвал меньше 160px -->
<div class="footer"></div>
<!-- Больше 160px -->
<div class="footer on-next-page_for-landscape"></div>
<!-- Больше 240px -->
<div class="footer on-next-page_for-landscape on-next-page_for-portrait"></div>
@media print {
/* Подвал меньше 160px */
.footer { position: absolute; bottom: 0 }
}
@media print and (orientation:landscape) {
/* Больше 160px */
.footer.on-next-page_for-landscape { position: static }
}
@media print and (orientation:portrait) {
/* Больше 240px */
.footer.on-next-page_for-portrait { position: static }
}
<style media="print and (orientation:portrait)">
.map {top: -35px}
</style>
<style media="print and (orientation:portrait)">
.map {top: 75px}
</style>
bgcolor, background
.selector {
-webkit-print-color-adjust: exact
}
Одно из предложений
@page {
print-color-adjust: exact
}
.selector {
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ffffff', GradientType=0 );
}
<div class='view'>
<img class='map' src='green.png'>
</div>
.view {
position: relative
}
.map {
position: absolute
top: 0; bottom: 0
left: 0; right: 0
}
<div class='view'>
<img class='map' src='green.png'>
</div>
.view {
position: relative
}
.map {
position: absolute
top: 0; bottom: 0
left: 0; right: 0
}
<div class='view'></div>
.view {
position: relative
}
.view::before {
position: absolute
top: 0; bottom: 0
left: 0; right: 0
content: url(green.png)
}
<div class='view'></div>
.view {
position: relative
}
.view::before {
position: absolute
top: 0; bottom: 0
left: 0; right: 0
content: url(green.png)
}
<div class='view'></div>
.view::before {
...
content: url(green.svg)
}
<svg width='100%' height='100%'>
<rect fill='#00ff00' width='100%' height='100%'/>
</svg>
<div class='view'></div>
.view::before {
...
content: url('data:image/svg+xml;<svg>...</svg>')
}
<svg width='100%' height='100%'>
<rect fill='#00ff00' width='100%' height='100%'/>
</svg>
<div class='view'></div>
.view::before {
...
content: url('data:image/svg+xml;base64,[data]')
}
<svg width='100%' height='100%'>
<rect fill='#00ff00' width='100%' height='100%'/>
</svg>
<div class='view'></div>
.view::before {
...
content: url('data:image/svg+xml;base64,[data]')
}
<svg width='100%' height='100%'>
<rect fill='#00ff00' width='100%' height='100%'/>
</svg>
content:url(SVG)
<div class='view'></div>
.view {
position: relative
overflow: hidden
}
.view::before {
position: absolute; z-index:-1
top: 0; bottom: 0
left: 0; right: 0
content: ''
border: solid green
border-width: 1000px 0 0
}
<div class='head i-bgcolor'></div>
<div class='foot i-bgcolor'></div>
.i-bgcolor {
position: relative
overflow: hidden
}
.i-bgcolor::before {
position: absolute; z-index:-1
top: 0; bottom: 0
left: 0; right: 0
content: ''
border-style: solid
border-width: 1000px 0 0
}
.head::before {
border-color: green
}
.foot::before {
border-color: red
}
<div class='head i-bgcolor'></div>
<div class='foot i-bgcolor'></div>
.i-bgcolor {
position: relative
overflow: hidden
}
.i-bgcolor::before {
position: absolute; z-index:-1
top: 0; bottom: 0
left: 0; right: 0
content: ''
border-style: solid
border-width: 1000px 0 0
}
.head:before {
border-color: green
filter: ...Microsoft.gradient( startColorstr='#ff008000' endColorstr='#ff008000' GradientType=0)
}
.foot:before {
border-color: red
filter: ...Microsoft.gradient( startColorstr='#ffff0000' endColorstr='#ffff0000' GradientType=0)
}
.view {
width: 300px
height: 200px
background: url(fox.png) 0 0 no-repeat
list-style: url(fox.png) inside
}
@media print {
.view {
display: list-item
}
}
<div class='view'></div>
.view {
position: relative
width: 300px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(fox.png)
}
<div class='view'></div>
.view {
position: relative
width: 300px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(fox.png)
}
<div class='view'></div>
.view {
position: relative
width: 300px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(fox.svg)
}
<svg width='300' height='200'>
<image xlink:href='fox.png' width='300' height='200' />
</svg>
<div class='view'></div>
.view {
position: relative
width: 300px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(fox.svg)
}
<svg width='300' height='200'>
<image xlink:href='fox.png' width='300' height='200' />
</svg>
<div class='view'></div>
.view {
position: relative
overflow: hidden
width: 400px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(small.fox.svg)
}
<svg width='9999' height='80'>
<defs>
<pattern id='myFox' width='9999' height='80'>
<image xlink:href='small.fox.png' width='100' height='80'/>
</pattern>
</defs>
<rect fill='url(#myFox)' width='9999' height='80'/>
</svg>
<div class='view'></div>
.view {
position: relative
overflow: hidden
width: 400px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(small.fox.svg)
}
<svg width='100' height='9999'>
<defs>
<pattern id='myFox' width='100' height='9999'>
<image xlink:href='small.fox.png' width='100' height='80'/>
</pattern>
</defs>
<rect fill='url(#myFox)' width='100' height='9999'/>
</svg>
<div class='view'></div>
.view {
position: relative
overflow: hidden
width: 400px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(small.fox.svg)
}
<svg width='9999' height='9999'>
<defs>
<pattern id='myFox' width='9999' height='9999'>
<image xlink:href='small.fox.png' width='100' height='80'/>
</pattern>
</defs>
<rect fill='url(#myFox)' width='9999' height='9999'/>
</svg>
<div class='view'></div>
.view {
position: relative
overflow: hidden
width: 400px
height: 200px
}
.view::before {
position: absolute
z-index:-1
content: url(small.fox.svg)
}
<svg width='9999' height='9999'>
<defs>
<pattern id='myFox' width='9999' height='9999'>
<image xlink:href='small.fox.png' width='100' height='80'/>
</pattern>
</defs>
<rect fill='url(#myFox)' width='9999' height='9999'/>
</svg>
...
border-image: url(box.png) 100 0 0 0 / auto repeat;
...
<div class='view'></div>
.view {
position: relative
overflow: hidden
width: 400px
height: 200px
}
.view::before {
position: absolute; z-index:-1
top: 0
left: 0
right: 0
content: ''
border-style: solid
border-width: 100px 0 0
border-image: url(fox.png) 100 0 0 0 / auto repeat
}
<div class='view'></div>
.view {
position: relative
overflow: hidden
width: 400px
height: 200px
}
.view::before {
position: absolute; z-index:-1
top: 0
left: 0
right: 0
content: ''
border-style: solid
border-width: 0 0 0 100px
border-image: url(fox.png) 0 0 0 100 / auto repeat
}
<div class='view'></div>
.view {
position: relative
overflow: hidden
width: 400px
height: 200px
}
.view::before {
position: absolute; z-index:-1
top: 0
left: 0
right: 0
content: ''
border-style: solid
border-width: 0 0 0 100px
border-image: url(fox.png) 0 0 0 100 / auto stretch
}
::before
+ border-color
::before
+ content: url(png)
::before
+ border-image: url(png)
+ repeat
::before
+ border-image: url(png)
+ stretch
Вадим Макишвили
makishvili@yandex-team.ru
Презентация: makishvili.github.io/print-and-go/index.html