I've made an interactive 16x16 grid, who's div
s grown and shrink based on screen size.
let x = 0;
let container = document.getElementById("container");
document.addEventListener('DOMContentLoaded', function() {
createLongContainers();
let longContainers = document.querySelectorAll(".longContainer");
createBoxes(longContainers);
});
function createLongContainers() {
for (var i = 0; i < 16; i ) {
let div = document.createElement('div');
div.className = "longContainer";
div.style.display = "flex";
div.style.flexDirection = "row"
var lcHeight = ((100 / 16) "%");
div.style.height = lcHeight;
div.style.width = "100vh";
container.appendChild(div);
}
}
function createBoxes(longContainers) {
longContainers.forEach((div) => {
for (var i = 0; i < 16; i ) {
let box = document.createElement('div');
box.className = "gridSquare";
let boxWidth = ((100 / 16) "%");
box.style.height = "100%";
box.style.width = boxWidth;
box.style.backgroundColor = "black";
box.onmouseover = function() {
var randomColor = Math.floor(Math.random() * 16777215).toString(16);
box.style.transitionDuration = "0s";
box.style.backgroundColor = "#" randomColor;
};
box.onmouseout = function() {
box.style.transitionDuration = "3s";
box.style.backgroundColor = "black";
}
div.appendChild(box);
}
});
}
#container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Colorful Grid</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body style="margin: 0;">
<div id="container"></div>
<!-- Removes white border around page-->
</body>
</html>
I can't figure out how to fill the screen with this grid, while maintaining their square shape and ability to shrink in relation to the screen size.
For example, when I change
div.style.width = "100vh";
to
div.style.width = "100vw";
and add more boxes so they aren't stretched, they lose their ratio when the screen size is changed.
I know I need to dynamically create fixed size div
s based on the current screen size, but I can't figure out how.
CodePudding user response:
I chanegd your script a little and sued CSS-Grid over Flexbox which will make everythign easier IMHO. Also you onyl need to run 1 script as it includes 256 boxes (16x16) instead of 16 rows that then again include 16 child boxes.
I also removed the style
-statements from JS completely. I add the styles through CSS to shorten the JS code.
Then I used aspect-ratio
to maintain a square-size. Alternativly you can hardcode it.
Then I used media queries
within CSS to check if the screen size is in landscape
or in portrait
-mode and set the width of the squares to either to
1fror
calc(100vh / 16)`.
Last but not least I use overflow: hidden
on the container to hide the elements that would not fit the viewport anymore. That is the onyl way to fill the entire screen without breaking the aspect-ration of the boxes.
let x = 0;
let container = document.getElementById("container");
document.addEventListener('DOMContentLoaded', function() {
createBoxes();
});
function createBoxes() {
document.querySelectorAll('#container').forEach((div) => {
for (var i = 0; i < 256; i ) {
let box = document.createElement('div');
box.className = "gridSquare";
box.onmouseover = function() {
var randomColor = Math.floor(Math.random() * 16777215).toString(16);
box.style.transitionDuration = "0s";
box.style.backgroundColor = "#" randomColor;
};
box.onmouseout = function() {
box.style.transitionDuration = "3s";
box.style.backgroundColor = "black";
}
div.appendChild(box);
}
});
}
#container {
display: grid;
height: 100vh;
width: 100vw;
overflow: hidden;
}
@media only screen and (orientation: portrait) {
#container {
grid-template-columns: repeat(16, calc(100vh / 16));
}
}
@media only screen and (orientation: landscape) {
#container {
grid-template-columns: repeat(16, 1fr);
}
}
.gridSquare {
aspect-ratio: 1 / 1;
background-color: black;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Colorful Grid</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body style="margin: 0;">
<div id="container"></div>
<!-- Removes white border around page-->
</body>
</html>
I saw your comment that you wanted to use 20px squares. I chanegd the script and CSS to adjust for that. I got rid of the media queries
and changed the the ammoutn of columns to repeat(auto-fill, minmax(20px, 1fr));
That will include as many columns of at least 20px and fill them with as many as possible. Then it upsize the columns to leave no white-space.
To create as many boxes as needed you can create an redicolous ammount of boxes. However this will cause seriose performance issues.
Therefor I wrote this little script:
var container = document.querySelector('#container');
var containerWidth = Math.floor(container.offsetWidth / 20),
containerHeight = Math.ceil(container.offsetHeight / 20);
var squareAmmount = containerWidth * containerHeight;
This script get the width and height of the viewport. It devides both by 20. The width can be roudned down but the height must be rounded up to allow the overflow. Then I multiply both values and get the sum of them. That sum is used in the loop as target so it will only create as many boxes as actually needed:
let x = 0;
let container = document.getElementById("container");
document.addEventListener('DOMContentLoaded', function() {
createBoxes();
});
function createBoxes() {
document.querySelectorAll('#container').forEach((div) => {
var container = document.querySelector('#container');
var containerWidth = Math.floor(container.offsetWidth / 20),
containerHeight = Math.ceil(container.offsetHeight / 20);
var squareAmmount = containerWidth * containerHeight;
for (var i = 0; i < squareAmmount; i ) {
let box = document.createElement('div');
box.className = "gridSquare";
box.onmouseover = function() {
var randomColor = Math.floor(Math.random() * 16777215).toString(16);
box.style.transitionDuration = "0s";
box.style.backgroundColor = "#" randomColor;
};
box.onmouseout = function() {
box.style.transitionDuration = "3s";
box.style.backgroundColor = "black";
}
div.appendChild(box);
}
});
}
#container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20px, 1fr));
height: 100vh;
width: 100vw;
overflow: hidden;
}
.gridSquare {
aspect-ratio: 1 / 1;
background-color: black;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Colorful Grid</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body style="margin: 0;">
<div id="container"></div>
<!-- Removes white border around page-->
</body>
</html>
CodePudding user response:
Is this what you want?
let x = 0;
let container = document.getElementById("container");
document.addEventListener('DOMContentLoaded', function () {
createLongContainers();
let longContainers = document.querySelectorAll(".longContainer");
createBoxes(longContainers);
});
function createLongContainers() {
for (var i = 0; i < 16; i ) {
let div = document.createElement('div');
div.className = "longContainer";
div.style.display = "flex";
div.style.flexDirection = "row"
div.style.justifyContent = "space-around"
var lcHeight = "100%";
div.style.height = lcHeight;
div.style.width = "100%";
container.appendChild(div);
}
}
function createBoxes(longContainers) {
longContainers.forEach((div) => {
for (var i = 0; i < 16; i ) {
let box = document.createElement('div');
box.className = "gridSquare";
box.style.backgroundColor = "black";
box.onmouseover = function () {
var randomColor = Math.floor(Math.random()*16777215).toString(16);
box.style.transitionDuration = "0s";
box.style.backgroundColor = "#" randomColor;
};
box.onmouseout = function () {
box.style.transitionDuration = "3s";
box.style.backgroundColor = "black";
}
div.appendChild(box);
}
});
}
#container{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
width: 100%;
}
.gridSquare {
height: calc(100vh / 16);
aspect-ratio: 1/1;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Colorful Grid</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body style="margin: 0;"> <div id="container"></div><!-- Removes white border around page-->
</body>
</html>
Also try resizing it, it looks interesting because of the transition.