Issue
I'm creating a Div that has a 32x32 tileset as a background-image. I want its minimum Height to be at least 80% of the viewport and its Width around 20% of the viewport, but I want the Height and Width to be a multiple of 32 so that none of the tiles get cut off. Is there a way to have the Div fulfill both of these conditions without hard-coding it? I want to avoid hard-coding these values because the viewport's size changes depending on what computer, tablet, or phone you view it on.
I'm a beginner in HTML / CSS, so I don't know a lot of the tools that are available. Any help would be appreciated! (Edited to add code snippet.)
/* Note: tower-sides.png is a 32x32 png with no transparency. */
/* Sidebar Tileset*/
--sidebarimg: url("/assets/main/img/tower-sides.png");
/* This section handles the Sidebars */
aside{
width: 20%;
background-color: var(--sidebarbg);
background-image: var(--sidebarimg);
font-size: smaller;
}
#left-sidebar{order: 1;}
#right-sidebar{order: 3;}
Solution
CSS-only solution (lacks browser support)
You can use CSS round()
to round 20vw
to the nearest 32px
.
Edit - you can optionally specify whether you want the round
CSS function to round down
, up
, or closest
:
width: round(down, 20vw, 32px);
height: round(down, 80vh, 32px);
So here's how the solution looks:
div {
background-image: url(https://placehold.co/32);
width: round(nearest, 20vw, 32px);
height: round(nearest, 80vh, 32px);
outline: 3px solid gray;
}
<div></div>
However note - as of Nov 2023 only Firefox and Safari support round()
.
CSS-only 2
This solution is supported by all major browsers, but will result in large HTML code. Moreover, the effect is purely visual and the actual width of the box will always be 20vw
.
This solution uses css grid with columns of a fixed 32px
size which wrap around responsively. By removing any borders and background on the main box, and putting the background image inside the children of the box, we get this solution:
div {
width: 20vw;
height: 80vh;
display: grid;
grid-template-columns: repeat( auto-fill, 32px );
grid-template-rows: repeat( auto-fill, 32px );
}
div > span {
background-image: url(https://placehold.co/32);
}
<div>
<span></span>
... many, many spans ...
<span></span>
</div>
But using this approach is not recommended.
Using JavaScript
I think the best method is this one - to do exactly what the CSS round()
function does, but using JavaScript. Ie, resize the container to the nearest 32px
.
In JavaScript, you have to wrap this around a resize
event listener so it re-adjusts every time the user resizes the viewport.
const div = document.querySelector("div");
function resizeDiv() {
div.style.width = Math.round(.2*window.innerWidth / 32) * 32 + "px";
div.style.height = Math.round(.8*window.innerHeigth / 32) * 32 + "px";
}
window.addEventListener("resize", resizeDiv);
resizeDiv();
div {
width: 20vw;
height: 80vh;
min-width: 32px;
min-height: 32px;
background-image: url(https://placehold.co/32);
}
<div></div>
Like with the first solution, you can choose whether to round the width/height down, up, or nearest.
- To round down, use
Math.floor(...)
- To round up, use
Math.ceil(...)
- To round to the nearest 32px, use
Math.round(...)
<- this is what the snippet above is using
Answered By - Krokodil
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.