4

I'd like any div element to resize when the viewport size changes, so generally I could use e.g. flex or 10em or % - but actually I'd like it only to resize in increments of 30 pixels, so it'd always align with a background.

Is this possible?

The only way I could think of is defunct - it might have been possible with the mod operator back in the day but not now?

Using modulus in css calc function

Also I could achieve this with media queries but to set that up for increments of only 30 pixels would be a nightmare.

The snippet below has a max-width of 210px and a min-width of 30px. As the browser resizes from wide to thin, it should jump in increments of 30px only.

.Mlt{
   background-color:grey;
   min-width:60px;
   max-width:210px;
}
<div class="Mlt">
    <p>Hello</p>
    <p>Content</p>
</div>
jamheadart
  • 5,047
  • 4
  • 32
  • 63
  • Could you provide a snippet? – Daniel_Knights Jun 28 '20 at 12:27
  • 1
    I put in a very basic snippet and I do mean basic, because I don't know where to begin tbh. – jamheadart Jun 28 '20 at 18:32
  • _"as the browser resizes from wide to thin, it should jump in increments of 30px only."_ When do you expect the increase/decrease in size? You say as the browser sizes, but you don't give any parameters. You could use `media queries` for the break point you expect it to increase/decrease. – disinfor Jun 28 '20 at 18:37
  • As I said in the question I thought I could use media queries but I think for a full screen this would be tens and tens of them, not really optimal. I found a similar question with the `mod` answer here but it's old. I was hoping there was another way to this other than media queries. https://stackoverflow.com/questions/29857411/how-to-incrementally-resize-div-with-browser-window – jamheadart Jun 28 '20 at 18:38
  • Oh and the decrease in size is always the widest possible - It'd snap to the largest width that was a multiple of 30px each time. – jamheadart Jun 28 '20 at 18:39

2 Answers2

4

CSS grid can do this but you will need an extra container. The trick is to create columns having 30px of width using auto-fit then you simply span all the created columns:

The use of jquery is only for demo purpose to show the width on resize. I also removed the max-width to easily test

console.log($('.Mlt > div').width());
$(window).resize(function() {
  console.log($('.Mlt > div').width());
})
.Mlt {
  min-width: 60px;
  display:grid;
  grid-template-columns:repeat(auto-fit,30px);
  /* justify-content: center; <-- use this if you want to center the div */
}

.Mlt > div {
  grid-column:1/-1; /* take all the columns */
  background-color: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="Mlt">
  <div >
    <p>Hello</p>
    <p>Content</p>
  </div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

It's not what I'd call easy on the eyes, but, this is the best solution I could come up with:

const div = document.querySelector('.Mlt');

window.addEventListener('resize', () => {
  if (div.clientWidth >= window.innerWidth - 20) {
    div.style.width = div.clientWidth - 30 + "px";
  } else if (div.clientWidth < window.innerWidth - 20) {
    div.style.width = div.clientWidth + 30 + "px";
  }

  // Display div width
  document.getElementById('div-width').innerHTML = div.style.width;
})
.Mlt {
  background-color: grey;
  min-width: 60px;
  max-width: 510px;
}
<div class="Mlt">
  <p>Hello</p>
  <p>Content</p>
</div>

<!-- Display div width -->
<div id="div-width"></div>

Relies on JS if that's what you're after. With CSS I don't see any other way than setting an unreasonable number of media queries, like you said.

The divs width increases and decreases by multiples of 30 when it hits the edge of the viewport. I've set minus 30 on window.innerWidth as that's what it needed in JSFiddle's preview window, you might need to tweak it a bit.

You can test it here: https://jsfiddle.net/L61sq3fd/1/

Daniel_Knights
  • 7,940
  • 4
  • 21
  • 49
  • 1
    I was hoping for css-only but I did consider that it'd only be possible with some JS sprinkles. Upvoted because it works and I'm trying both answers to see what feels best. – jamheadart Jun 29 '20 at 05:52
  • Other answer is definitely better than mine! – Daniel_Knights Jun 29 '20 at 06:35
  • 1
    Yeah it's working very well, I extended it to 25px rows too and basically have an isometric grid background with items that snap into place no matter what size the window! – jamheadart Jun 29 '20 at 06:46