I do Etch-a-Sketch – https://www.theodinproject.com/lessons/foundations-etch-a-sketch . But I want do something more than the assignment.
I need do this ONLY with Flexbox and JavaScript (without CSS Grid)
-
When I do gridContainer.style.height = "100vh" , it is a little bit more than screen height. So I do 97vh. Is there another solution?
-
I want add width=100vw (replace height = "97vh") ONLY for mobile screen. But I cannot do this with media query javasript. (The result is grid container height more than width.) Maybe I don’t know something? How can I do this?
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="./styles.css" />
<script src="./script.js" defer></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Etch-a-Sketch</title>
</head>
<body>
<div id="gridUser">
<h1>Etch-a-Sketch</h1>
<form id="gridForm">
<p><label for="gridInput">Enter a number of squares per side: 1...100</label></p>
<p><input id="gridInput" type="text"></p>
<p><legend>Choose mouse hover color</legend></p>
<p>
<input id="gridRadioYellow" name="gridRadio" value ="yellow" type="radio" checked>
<label for="gridRadioYellow"> Yellow</label>
<input id="gridRadioRandomize" name="gridRadio" value ="randomize" type="radio">
<label for="gridRadioRandomize"> Randomize</label>
<input id="gridRadioRandomizeEverySquare" name="gridRadio" value ="randomizeEverySquare" type="radio">
<label for="gridRadioRandomizeEverySquare"> Randomize every square</label>
</p>
<p><button type="submit">Submit</button></p>
</form>
<div id="gridText"></div><br/>
</div>
<div id="gridContainer"></div>
</body>
</html>
* {
box-sizing: border-box;
font-family: Arial, sans-serif;
text-align: center;
}
body {
display: flex;
flex-flow: row wrap;
justify-content: flex-start;
}
#gridUser, #gridContainer {
flex: 1 1 0%;
}
#gridInput {
text-align: left;
}
// also add functional for yellow color (not randomize) and for randomize every square
let gridContainer = document.querySelector("#gridContainer");
let gridSize = 16*16;
let gridSquares = "";
let mouseSquares = [];
let mouseHoveringColor = "";
getGridPerSide();
function getGridPerSide() {
let gridForm = document.querySelector("#gridForm");
gridForm.addEventListener("submit", (e) => {
e.preventDefault();
let gridInput = document.querySelector("#gridInput");
let gridRadio = document.querySelectorAll(`input[name="gridRadio"]`);
let gridRadioChecked = "";
let gridText = document.querySelector("#gridText");
mouseHoveringColor = "";
for (const gridRadioOne of gridRadio) {
if (gridRadioOne.checked) {
gridRadioChecked = gridRadioOne.value;
break;
}
}
if (isNaN(gridInput.value) || gridInput.value < 1 || gridInput.value > 100) {
gridText.innerHTML = `Enter a <em>right</em> number <strong>from 1 to 100</strong>`;
} else if (gridRadioChecked === "yellow") {
gridText.innerHTML = `
The grid has <em>${gridInput.value}*${gridInput.value}</em> squares<br/>
The mouse hover color is <strong>yellow</strong><br/>
`;
mouseHoveringColor = "yellow"; // value for doMouseHovering()
} else if (gridRadioChecked === "randomize") {
gridText.innerHTML = `
The grid has <em>${gridInput.value}*${gridInput.value}</em> squares<br/>
The mouse hover color is <strong>randomize</strong><br/>
`;
mouseHoveringColor = "randomize"; // value for doMouseHovering()
} else {
gridText.innerHTML = `
The grid has <em>${gridInput.value}*${gridInput.value}</em> squares<br/>
The mouse hover color is <strong>randomize every square</strong><br/>
`;
mouseHoveringColor = "randomizeEverySquare"; // value for doMouseHovering()
}
gridSize = gridInput.value * gridInput.value;
createGrid();
});
}
function createGrid() {
gridContainer.innerHTML = ""; // grid clean for new submit
for (let i=0; i < (gridSize); i++) {
gridSquares = document.createElement("div");
gridSquares.classList.add("gridSquares");
gridContainer.appendChild(gridSquares);
gridSquares.style.cssText = `
width: calc(100% / ${gridInput.value});
height: calc(100% / ${gridInput.value});
background-color: #eee;
border: 1px solid #ccc;
`;
gridContainer.style.cssText = `
height: 97vh;
width: auto;
display: flex;
flex-wrap: wrap;
aspect-ratio: 1/1;
`;
mouseSquares.push(gridSquares); // create array for doMouseHovering()
}
doMouseHovering();
}
function doMouseHovering() {
// need mouseBackgroundColor for calculate "randomize" (NOT for "randomizeEverySquare")
let mouseBackgroundColor = "";
if (mouseHoveringColor === "yellow") {
mouseBackgroundColor = "yellow";
} else if (mouseHoveringColor === "randomize") {
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
mouseBackgroundColor = `rgb(${r}, ${g}, ${b})`;
}
mouseSquares.forEach(gridSquares => {
gridSquares.addEventListener('mouseover', () => {
if (mouseHoveringColor === "yellow") {
gridSquares.style.backgroundColor = mouseBackgroundColor;
} else if (mouseHoveringColor === "randomize") {
gridSquares.style.backgroundColor = mouseBackgroundColor;
} else {
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
gridSquares.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
}
});
});
}
I tried do this with CSS media query and JavaScript media query. The result is grid container height more than width. But the grid container must be square.
2
Answers
I found a simple solution. Change vh and vw on vmin. (And now I don't need media queries for mobile screens.)
I managed to get it to fit within the container by using the
gap: 0px
property with the flex-box container.I also used CSS Object Model to calculate out the exact dimensions for each square to make sure that it fits within the container’s computed dimensions.
There’s many different ways to do this… this was just one such way
You could even create the canvas from javascript using document.createElement("canvas") at the start.