4

From this question I got a very nice code to render an A4 sheet onto my web app. I adapted it to fill up my needs. Here is the code snippet :

.book {
  margin: 0;
  padding: 0;
  background-color: #FAFAFA;
  font: 12pt "Tahoma";
}

* {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
}

.page {
  display: block;
  width: 21cm;
  height: 29.7cm;
  margin: 1cm auto;
  border: 1px #D3D3D3 solid;
  border-radius: 5px;
  background: white;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}

.subpage {
  margin: 1cm;
  width: 19cm;
  height: 27.7cm;
  outline: 0cm #FAFAFA solid;
}

@page {
  size: A4;
  margin: 0;
}

@media print {
  .page {
    margin: 0;
    border: initial;
    border-radius: initial;
    width: initial;
    min-height: initial;
    box-shadow: initial;
    background: initial;
    page-break-after: always;
  }
}
<div class="container-fluid">
  <div class="book">
    <div class="page">
      HEADER
      <div class="subpage" id='editor-container'>CONTENT</div>
    </div>
  </div>
</div>

This code is very nicely rendering what I want to do on a computer screen. But when you use it on a small-sized screen, for example a tablet, this isn't very convenient.

How can I make this code responsive to suits the screen where it would be displayed ?

Basically, it would be nice if the sheet resizing to be entirely displayed on the screen, or at least from the left to the right side and users could scrolldown to display the content from the top to the bottom.

Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
M. Ozn
  • 1,018
  • 1
  • 19
  • 42
  • I've made several applications that work with the concept of fixed-size pages, and yeah, they're tricky to make responsive. Will there be more than one page on the screen at any given time? – Alex Jegtnes Aug 07 '17 at 10:31
  • Yes it will be possible to add pages so it's why I thinks it's better to only display entirely from the left to the right and let the user scroll down. Something like make the width (21cm) resizable and fully displayed then adjust the height to get something with reals proportions ? – M. Ozn Aug 07 '17 at 10:37
  • @MaximeOzenne Does my solution help you or no? – Vadim Ovchinnikov Aug 07 '17 at 10:44
  • It looks like it's what I need, I'll try it in half an hour. Thanks ! – M. Ozn Aug 07 '17 at 10:57
  • @MaximeOzenne But probably you'll have to change how content is scaled (like use `vw` units for everything or some other ways) because this way you won't get content scaling. – Vadim Ovchinnikov Aug 07 '17 at 11:03

2 Answers2

3

Use vw units instead of cm to get desired effect. 1vw is 1% of screen width.

I've multiplied values by 100 / 23 to make page width (21cm) and margins (1cm each) taking whole screen width.

.book {
  margin: 0;
  padding: 0;
  background-color: #FAFAFA;
  font: 12pt "Tahoma";
}

* {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
}

.page {
  display: block;
  width: calc(100 / 23 * 21vw);
  height: calc(100 / 23 * 29.7vw);
  margin: calc(100 / 23 * 1vw) auto;
  border: 1px #D3D3D3 solid;
  border-radius: 5px;
  background: white;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}

.subpage {
  margin: calc(100 / 23 * 1vw);
  width: calc(100 / 23 * 19vw);
  height: calc(100 / 23 * 27.7vw);
  outline: 0cm #FAFAFA solid;
}

@page {
  size: A4;
  margin: 0;
}

@media print {
  .page {
    margin: 0;
    border: initial;
    border-radius: initial;
    width: initial;
    min-height: initial;
    box-shadow: initial;
    background: initial;
    page-break-after: always;
  }
}
<div class="container-fluid">
  <div class="book">
    <div class="page">
      HEADER
      <div class="subpage" id='editor-container'>CONTENT</div>
    </div>
  </div>
</div>

But probably you'll have to change how content is scaled (like use vw units for everything or some other ways) because this way you won't get content scaling.


Another option is to use JavaScript to get screen width and adjust it your need using transform: scale. Demo:

function adjustZoomLevel() {
  var documentWidth = window.innerWidth
    || document.documentElement.clientWidth
    || document.body.clientWidth;
    
  // 1 cm = 37.795276px;
  var zoomLevel = documentWidth / (23 * 37.795276);
  
  // stop zooming when book fits page
  if (zoomLevel >= 1) return;
  
  document.querySelector(".book").style.transform = "scale(" + zoomLevel + ")";
}

adjustZoomLevel();

window.addEventListener("resize", adjustZoomLevel);
.book {
  margin: 0;
  padding: 0;
  background-color: #FAFAFA;
  font: 12pt "Tahoma";
  transform-origin: 0 0;
}

* {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
}

.page {
  display: block;
  width: 21cm;
  height: 29.7cm;
  margin: 1cm auto;
  border: 1px #D3D3D3 solid;
  border-radius: 5px;
  background: white;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}

.subpage {
  margin: 1cm;
  width: 19cm;
  height: 27.7cm;
  outline: 0cm #FAFAFA solid;
}

@page {
  size: A4;
  margin: 0;
}

@media print {
  .page {
    margin: 0;
    border: initial;
    border-radius: initial;
    width: initial;
    min-height: initial;
    box-shadow: initial;
    background: initial;
    page-break-after: always;
  }
}
<div class="container-fluid">
  <div class="book">
    <div class="page">
      HEADER
      <div class="subpage" id='editor-container'>CONTENT</div>
    </div>
  </div>
</div>
Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
  • This is working pretty good ! Now I have to find a way to scale the font size of the doc and all would be done. Thanks you ! – M. Ozn Aug 07 '17 at 12:11
  • @MaximeOzenne Glad that it helped you. – Vadim Ovchinnikov Aug 07 '17 at 12:11
  • @MaximeOzenne Added another option with little JavaScript but it will remove need to rewrite CSS. – Vadim Ovchinnikov Aug 07 '17 at 13:01
  • I used back my css to try your script. It seems to works well for the font size but the page div isn't resizing well. Actually I have a page which going out of the screen – M. Ozn Aug 07 '17 at 13:20
  • Hi @Vadim, did you run your code snippet in full screen ? You'll see there is an issue. This solution seems to be the one I need but currently your code isn't working well (Or maybe I have a serious browser problem ?) Please can you take a look at your code I would really appreciate it. Thanks – M. Ozn Aug 10 '17 at 15:02
  • @MaximeOzenne Yes, I ran code in code snippet even if full screen and it performs well in Chrome 59, Firefox, IE11, MS Edge. I'm on Windows 10. I suppose we are talking about solution #1. – Vadim Ovchinnikov Aug 10 '17 at 15:11
  • No actually I'm talking about the solution 2 with the javascript implementation – M. Ozn Aug 10 '17 at 15:19
  • 1
    @MaximeOzenne Just removed zooming in (`if (zoomLevel >= 1) return;`). Does this look good enough? https://jsfiddle.net/b97qb42w/ – Vadim Ovchinnikov Aug 10 '17 at 15:49
1

If you don't need this to be super-precise, Vadim's approach works just fine, and is a lot less hacky than what I'm about to suggest. However, for my use-cases, subpixel scaling will result in things not always being 100% correctly positioned, depending on the complexity of your page. If you need everything to be perfectly scaled down/up like a PDF, the only way you can do this is with CSS' transform: scale() property and media queries.

e.g.

.page {
    width: 29.7cm;
}

@media screen and (max-width: 800px) {
    .page {
          transform: scale(0.8);
    }
}

@media screen and (max-width: 600px) {
    .page {
          transform: scale(0.6);
    }
}
/* etc */

This is mostly a fiddly process, and will require playing around to get the right amounts of scaling, but it's been the only thing that consistently worked for me with the fewest layout quirks.

One thing you will stumble across is that transform: scale makes the page smaller, it doesn't actually "move" the page accordingly in the document. They will visibly shrink, but still take up the same amount of space, so you'll get increased margins between the pages when you scale them down. This can be mitigated by adding negative margins to the pages. Assuming they're stacked down and scroll vertically:

.page {
    width: 29.7cm;
}

@media screen and (max-width: 800px) {
    .page {
          transform: scale(0.8);
          margin-bottom: -5cm;
    }
}

@media screen and (max-width: 600px) {
    .page {
          transform: scale(0.6);
          margin-bottom: -10cm;
    }
}

Of course, those transform values are not to scale (ba-dum-tish), so you'll have to play around and find the correct values that work for you, should you go down this path.

Alex Jegtnes
  • 177
  • 10
  • thanks for your answer ! It seems to require a lot of work to get something really accurate so I would try with the Vadim's answer and get back to your code if it doesn't fit my needs – M. Ozn Aug 07 '17 at 12:08