Распечатай Яндекс.Карты

Вадим Макишвили, WSD декабрь 2013

Распечатай Яндекс.Карты
Вадим Макишвили, WSD декабрь 2013

Конкуренты

  1. Google Maps
  2. Yahoo! Maps
  3. Bing Maps
  4. MapQuest
  5. Wikimapia
  6. 2GIS
  1. OpenStreetMap
  2. Géoportail
  3. Apple Maps
  4. Nokia Maps
  5. ViaMichelin
  6. Seat Pagine Gialle

...и это ещё не все

Какая нужна карта?

чистая

удобная

подробная

полная

наглядная

Print & Go!

Критерии качества:

А4 формат

21х29cm

Google Maps

15х15cm

Google Maps

Google Maps

Google Maps

Google Maps

Google Maps

Google Maps

Google Maps

Google Maps

Yahoo! Maps

15х10cm

Yahoo! Maps

Microsoft Bing

12х12cm

3х3cm

Microsoft Bing

Microsoft Bing

Microsoft Bing

Рамблер Карты

15х15cm

Рамблер Карты

Рамблер Карты

Карты Mail.ru

15х12cm

Карты Mail.ru

Карты Mail.ru

Яндекс.Карты до 2013 года

15х15cm

Яндекс.Карты до 2013 года

Яндекс.Карты до 2013 года

Яндекс.Карты до 2013 года

Яндекс.Карты до 2013 года

Недостатки существующих решений:

Но!

Печать на
Яндекс.Картах

Размеры карты:

20 х 27cm

Печать на
Яндекс.Картах

Как мы это сделали?

... Quirks again?

1998

2012

Дальше будет:

В поисках раскладки

Шапка
Карта
Подвал

В поисках раскладки

            Quirks Mode
            <table height='100%'>
                ...
            </table>
            
            td.map {
                height: 100%
            }
        
<td> Шапка </td>
<td class='map'> Карта </td>
<td> Подвал </td>

В поисках раскладки

            Javascript?
        
<td> Шапка </td>
<td class='map'> Карта </td>
<td> Подвал </td>

Javascript:(

Хочется красоты

            if (page.orientation === 'landscape') {
                // do something
            }
        
            if (page.size.width === '210mm') {
                // do something
            }
        

CSS for printer

            @media print and (orientation:landscape) {
                // do something
            }
            
        

@rules

Nitro

WebCore

Webkit2

V8

WebCore

Chromium

V8

Blink

Chromium

@page

            /* Обнулить поля */
            @page {
                margin: 0
            }
        

@page

            /* Обнулить поля */
            @page {
                margin: 0
            }
        
file://localhost/Users/makishvili/projects/print-and-go/page-zero.html
05.07.13

@page

            /* Обнулить поля */
            @page {
                margin: 0
            }
        

Не работает?

12

@page

            /* Изменить поля */
            @page {
                margin: 1cm
            }
        

Заработало!

12

@page

            /* Изменить поля */
            @page {
                margin: 1cm
            }
        

Точка отсчёта -
дефолтные отступы,
а не край листа

12

@page size

            /* Принудительно задать ориентацию */
            @page {
                size: landscape
            }
        

@page name

            /* Группировка свойств */
            @page myName {
                font-size: 18px
                padding: 10px
            } 
            div {
                page: myName
            }
        

@page name. Фильтрация браузеров?

            @page chromePage { margin: 0 }
            body.chrome { page: chromePage }
            
            @page operaPage { margin: 5mm } 
            body.opera { page: operaPage }
        

@page name. Увы :(

            @page { margin: 0 } 
            null
            
            @page operaPage { margin: 5mm }
            body.opera { page: operaPage }
        
12

@document: фильтруем Firefox

            @page { margin: 0 } 
            null
            @-moz-document regexp('*') {
                @page {
                    margin-top: 1cm;
                    margin-bottom: 1cm;
                }
            }
        

Media-queries

Ориентация листа

            @media print and (orientation:portrait) {
                /* стили только для портрета */
            } 
            @media print and (orientation:landscape) {
                /* стили только для альбома */
            }
        
9+
12-

Раскладка

Шапка
Карта
Подвал

1. Таблица

<td> Шапка </td>
<td class='map'> Карта </td>
<td> Подвал </td>
            table, td.map {
                height: 100%
            }
        

1. Таблица

<div> Шапка </div>
<div class='map'> Карта </div>
<div> Подвал </div>
            div {
                display: table-cell
            }
            
            .map {
                height: 100%
            }
        

1. Таблица

  • нет min-height и max-height

CSS 2.1 не определяет поведение min-height и max-height в таблицах, поэтому любая реалиция этих свойств (применительно к таблицам) - CSS2.1-совместимая

MDN
  • нет overflow:hidden внутри ячейки

2. Позиционирование

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            div {
                position: absolute
                left: 0
                right: 0
            }
            .head {
                top: 0
                height: 100px
            }
            .map {
                top: 100px
                bottom: 100px
            }
            .foot {
                bottom: 0
                height: 100px
            }
        

2. Позиционирование

  • не работает page-break-before

User Agents must apply these properties to block-level elements in the normal flow of the root element.

CSS2 specification
  • нужна фиксированная высота подвала или javascript

3. Поток

<div class='map'> Карта </div>
            .map {
                height: 100%
            }
        

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .map {
                height: 100%
            }
            .head, .foot {
                position: absolute
                left: 0
                right: 0
            }
            .head {
                top: 0
            }
            .foot {
                bottom: 0
            }
        

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .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)'>
        

Подождите, а что с IE?

            <meta ...  content='IE=EmulateIE7'>
        

IE9 печатает
хуже, чем IE7 o_O

Большая картинка
в маленьком окне

            <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
            
9
на печати

Большая картинка
в маленьком окне

            <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
            
9
на печати

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .map {
                height: 100%
            }
            .head, .foot {
                position: absolute
                left: 0
                right: 0
            }
            .head {
                top: 0
            }
            .foot {
                bottom: 0
            }
        

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .map {
                height: 100%
            }
            .head, .foot {
                position: absolute
                left: 0
                right: 0
            }
            .head {
                top: 0
            }
            .foot {
                bottom: 0
            }
        
9
на печати

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .map {
                height: 100%
            }
            .head, .foot {
                position: absolute
                left: 0
                right: 0
            }
            .head {
                top: 0
            }
            .foot {
                bottom: 0
            }
        
9
на печати

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .map {
                height: 100%
            }
            .head, .foot {
                position: absolute
                left: 0
                right: 0
            }
            .head {
                top: 0
            }
            .foot {
                bottom: 0
            }
        
12 on Mac

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .map {
                height: 100%
            }
            .head, .foot {
                position: absolute
                left: 0
                right: 0
            }
            .head {
                top: 0
            }
            .foot {
                bottom: 0
            }
        
12 on Mac

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .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 
                }

                
            
12 on Mac

3. Поток + «наляпки»

<div class='head'> Шапка </div>
<div class='map'> Карта </div>
<div class='foot'> Подвал </div>
            .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 
                }


                
            
12 on Mac

Фильтруем браузеры

Фильтруем браузеры

            (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);
                }
            }());
        

100% листа

<div class='map'> Карта </div>
            html, body {
                height: 100%
            }
            .map {
                width: 100%
                height: 100%
            }
        

100% листа

<div class='map'> Карта </div>
            html, body {
                height: 100%
            }
            .map {
                width: 100%
                height: 100%
            }
        
25
6

100% листа

<div class='map'> Карта </div>
            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 }
            }
        
25
6

Предпросмотр
печати
врёт

@page

            /* Обнулить поля */
            @page {
                margin: 0
            }
        

@page

            /* Обнулить поля */
            @page {
                margin: 0
            }
        

@page

            /* Обнулить поля */
            @page {
                margin: 0
            }
        

Молодец!

12

@page

            /* Обнулить поля */
            @page {
                margin: 0
            }
        

Молодец!

18+

Что-то здесь
неправильно

Линии?!

Линии?!

Javascript;)

События

5+
6+

Match @media

            if (window.matchMedia(' (min-width: 400px) ').matches) {
                // do something
            }
        
5.1

Помните, мечтали о красоте...

Неужели, сбылось? :)

            if (page.orientation === 'landscape') {
                // do something
            }
        


            if (window.matchMedia('print and (orientation: landscape)').matches) {
                // do something
            }
        

Match "@media print"

Match "@media orientation"

            if (window.matchMedia('print').matches) {
                // do something
            }
        
5.1


            if (window.matchMedia('print and (orientation: landscape)').matches) {
                // do something
            }
        

TJ VanToll
"Detecting Print Requests with JavaScript"


http://clck.ru/8vbdS

Адаптивный комментарий

5 строк

Хочется Element Queries:

            .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
            }
        

15 строк

15 ?

10 строк

Хочется Media + Element Queries

            @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 }
            }
        

15 строк

10 строк

Масштабирование карты

Неточный
центр карты

Неточный центр
карты

Неточный центр
карты

Шапка
Подвал

Неточный центр
карты

Шапка
Панорама
Подвал
Шапка
Панорама
Подвал
Шапка
Подвал

Переместить центр
карты

            <style media="print and (orientation:portrait)">
                .map {top: -35px}
            </style>
        
Шапка
Подвал

Переместить центр
карты

            <style media="print and (orientation:portrait)">
                .map {top: 75px}
            </style>
        
Шапка
Панорама
Подвал

jQuery.injectCSS


http://clck.ru/8hvkH

Фон

                bgcolor, background
            

CSSWG: «Как включить печать фона?»


http://clck.ru/8hLnN

CSSWG: «Как включить печать фона?»

            .selector {
                -webkit-print-color-adjust: exact
            }
        

Все браузеры печатают...

<div class='map'> Карта </div>

Больше белого!

IE не печатает белый

А так печатает

            .selector {
              filter: progid:DXImageTransform.Microsoft.gradient(
                    startColorstr='#ffffff',
                    endColorstr='#ffffff',
                    GradientType=0 );
            }
        
8-

Фоновый цвет

Фоновый цвет

1. Экстраразметка с картинкой

            <div class='view'>
                <img  class='map' src='green.png'>
            </div>
            
            .view {
                position: relative
            }
            .map {
                position: absolute
                top: 0; bottom: 0
                left: 0; right: 0
            }
        
Фоновый цвет

1. Экстраразметка с картинкой

            <div class='view'>
                <img  class='map' src='green.png'>
            </div>
            
            .view {
                position: relative
            }
            .map {
                position: absolute
                top: 0; bottom: 0
                left: 0; right: 0
            }
        
Старьё!
Фоновый цвет

2. Псевдоэлемент + PNG

            <div class='view'></div>
            
            .view {
                position: relative
            }
            .view::before {
                position: absolute
                top: 0; bottom: 0
                left: 0; right: 0
            
                content: url(green.png)
            }
        
Фоновый цвет

2. Псевдоэлемент + PNG

            <div class='view'></div>
            
            .view {
                position: relative
            }
            .view::before {
                position: absolute
                top: 0; bottom: 0
                left: 0; right: 0
            
                content: url(green.png)
            }
        
Фоновый цвет

2. Псевдоэлемент + SVG

            <div class='view'></div>
            
            .view::before {
                ...
                content: url(green.svg)
            }

            
            <svg width='100%' height='100%'>
                <rect fill='#00ff00' width='100%' height='100%'/>
            </svg>
        
Фоновый цвет

2. Псевдоэлемент + 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>
        
Фоновый цвет

2. Псевдоэлемент + 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>
        
Фоновый цвет

2. Псевдоэлемент + 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>
        
12
на печати
                content:url(SVG)
            
Фоновый цвет

3. Border

            <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
            }
        
Фоновый цвет

3. Border - i-блок

            <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
            }
        
Фоновый цвет

3. Border - i-блок

            <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)
            }
        
Утверждено

Фоновое изображение

Одиночная фоновая картинка

1. Маркер списка

            .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
                }
            }
        
Одиночная фоновая картинка

2. Псевдоэлемент + PNG

            <div class='view'></div>
            
            .view {
                position: relative
            
                width: 300px
                height: 200px
            }
            .view::before {
                position: absolute
                z-index:-1
            
                content: url(fox.png)
            }
        
Одиночная фоновая картинка

2. Псевдоэлемент + PNG

            <div class='view'></div>
            
            .view {
                position: relative
            
                width: 300px
                height: 200px
            }
            .view::before {
                position: absolute
                z-index:-1
            
                content: url(fox.png)
            }
        
Утверждено
Одиночная фоновая картинка

3. Псевдоэлемент + опять 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>
        
Одиночная фоновая картинка

3. Псевдоэлемент + опять 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>
        
12
Размноженная фоновая картинка

1. Псевдоэлемент + 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>
        
Размноженная фоновая картинка

1. Псевдоэлемент + 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>
        
Размноженная фоновая картинка

1. Псевдоэлемент + 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>
        
Размноженная фоновая картинка

1. Псевдоэлемент + 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>
        
12
Размноженная фоновая картинка

2. Border-image

            ...
            border-image: url(box.png) 100 0 0 0 / auto repeat;
            ...
        
Размноженная фоновая картинка

2. Border-image

            <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
            }
        
Размноженная фоновая картинка

2. Border-image

            <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
            }
        
Растянутая фоновая картинка

3. Бонус

            <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
            }
        

Распечатай Яндекс.Карты

Вадим Макишвили
makishvili@yandex-team.ru



Презентация: makishvili.github.io/print-and-go/index.html