Демо
https://so51099397.surge.sh/
(мне кажется, что исправление, которое я реализовал, слишком много, но я не думаю, что есть какой-то другой способ решить проблему)
(Если вам интересно, почему я разместил сайт вместо чего-то вроде SO snippet или jsfiddle, я объяснил в комментарии)
Объяснение
Почему я получаю "мобильный" вид в печати?
width of A4 = 210mm ≈ 8.27 in ≈ 595 px (72 dpi)
xs
применяется, когда width < 768px
- Технически то, что делает Chrome, правильно, а то, что делают другие браузеры, неверно
Как это исправить?
- Bootstrap написан в мобильном шаблоне.
- Значение таблицы стилей выглядит примерно так:
.col-xs-12 {
width: 100%;
}
@media (min-width: 768px){
.col-sm-6 {
width: 50%;
}
}
- Теперь каким-то образом, если я разверну правила внутри
@media (min-width: 768px)
только во время печати, моя проблема будет решена.
- Чтобы реализовать это, мы получим все правила внутри
@media (min-width: 768px)
с использованием document.styleSheets
(не забудьте добавить crossorigin="anonymous"
в начальной загрузке <link>
, иначе вы получите ошибку при доступе к таблице стилей)
- Как только у нас будут все эти стили, мы обернем их в
<style>
и добавим в <head>
в beforeprint
событие
- В случае
afterprint
мы удалим это <style>
Код (как в демоверсии):
window.addEventListener("beforeprint", function(){
let printStyleSheet = document.createElement("style");
printStyleSheet.classList.add("print-stylesheet");
document.head.appendChild(printStyleSheet)
let printRulesText = "";
Array.from(document.styleSheets).forEach(styleSheet => {
Array.from(styleSheet.cssRules)
.filter(rule => rule.media && /(min-width: 768px)/g.test(rule.media.mediaText))
.forEach(rule => {
Array.from(rule.cssRules).forEach(rule => printRulesText += rule.cssText)
})
})
printStyleSheet.innerHTML = printRulesText;
})
window.addEventListener("afterprint", function(){
Array.from(document.querySelectorAll(".print-stylesheet")).forEach(style => style.remove())
})
Примечание: Это даст вам представление планшета (см), если вы хотите средний рабочий стол (md), вам придется развернуть оба, min-width: 768px
, а также min-width: 992px
аналогично для большой рабочий стол (LG) также
Будет ли это работать?
- Работает для кода в вопросе
- Должно работать и для других компонентов.
Можно ли это исправить, применив html, body { width: 769px }
во время печати? (как 769> 768)
- Нет, это не будет работать, потому что медиа-запросы работают на
viewport
, а не на ширину html или body
Хорошо, могу ли я добавить <meta name="viewport" content="width=769">
и удалить другие мета области просмотра во время печати? (как 769> 768)
- Умм ... Нет. Это не работает. (Я думаю, что это должно быть, но как-то не работает)
Есть ли другие исправления?
- Переопределить вручную
xs
стили, такие как @Arex did
Получите исходный код начальной загрузки css и измените его с помощью print
медиа-запросов примерно так:
.col-xs-12 {
width: 100%;
}
@media (min-width: 768px){
.col-sm-6 {
width: 50%;
}
}
/* add such rules everywhere */
@media print{
.col-sm-6 {
width: 50%;
}
}
- Поместите все содержимое текущей страницы в
iframe
с width: 100%; height: 100%; border: none;
и сделайте все остальное display: none;
. Но я чувствую, что это не сработает, потому что если iframe
получит полосу прокрутки, содержимое из вида не будет напечатано. Также выглядит гораздо более хакерски
PS: Это довольно очевидно, но позвольте мне прямо сказать это ... Реализованное исправление (как видно из демонстрации) не исправляет только систему координат или фрагмент в вопросе ... Но исправляет поведение ВСЕ компоненты (кнопка, таблица, входы, сетка и т. д.) путем имитации медиазапроса min-width: 768px
. Это то, что хочет ОП. Индивидуальная фиксация компонентов