Creating a flexible grid layout using Flexbox and JavaScript media queries to dynamically adjust container size

I enjoy working on Etch-a-Sketch projects from The Odin Project, but I am looking to take it a step further than just the assignment.

I want to challenge myself by achieving this solely with Flexbox and JavaScript, without involving CSS Grid.

  1. When I set gridContainer.style.height = "100vh", it extends slightly beyond the screen height. So, I adjusted it to 97vh. Is there a better solution for this?

  2. I aim to add width=100vw (instead of height = "97vh") exclusively for mobile screens. However, I can't figure out how to do this with a JavaScript media query. It results in the grid container having more height than width. Am I missing something? How should I approach this?

Answer №1

By setting the gap: 0px property in the flex-box container, I successfully made it fit within the container.

To ensure that each square fits perfectly within the container, I utilized the CSS Object Model to calculate and adjust their dimensions accordingly.

There are numerous methods to achieve this task, and this was just one of them.

class XSquare extends HTMLElement {
  constructor() {
    super();
    //   this.style.backgroundColor = 'white';
    this.addEventListener('mouseenter', () => this.style.backgroundColor = 'black');

  }
}

customElements.define('x-square', XSquare);


function createGrid(size) {
  const container = document.getElementById('container');
  container.innerHTML = ''; // Clear previous grid
  container.style.padding = 0 + 'px';
  container.style.margin = 0 + 'px';
  container.style.width = 100 + '%';
  container.style.height = 100 + '%';
  container.style.gridTemplateColumns = `repeat(${size}, 1fr)`;

  var containerWidth = container.attributeStyleMap.get("width").value;
  var containerHeight = container.attributeStyleMap.get("height").value;
  var sqSize = CSS.percent(Math.floor(Math.min(containerWidth / size, containerHeight / size)));
  container.style.height = sqSize * size;
  container.style.width = sqSize * size;

  for (let i = 0; i < size * size; i++) {
    const square = document.createElement('x-square');

    square.style.maxWidth = sqSize
    square.style.maxHeight = sqSize
    square.style.minWidth = sqSize
    square.style.minHeight = sqSize
   
    container.appendChild(square);
  }
}

document.getElementById('resize').addEventListener('click', () => {
  const newSize = prompt('Enter new grid size (max 100)', 16);
  if (newSize !== null && newSize <= 100) {
    createGrid(newSize);
  }
});

createGrid(16); // Initial grid creation
#container {
  display: flex;
  flex-wrap: wrap;
  flex: 0 0 0 0;
  width: 101%;
  /* Fixed width for the container */
  height: 99%;
  margin: 0px;
  padding: 0px;
  border: 2px solid black;
   // make gap between items 0px
   gap: 0px 
}

x-square {
  aspect-ratio: 1;
  /* Ensures squares remain square */
  border: 1px solid black;
  transition: background-color 0.3s;
  /* Smooth color transition */
  box-sizing: border-box;
  max-width: 20px;
  max-height: 20px;
  margin: 0px;
  padding: 0px;
 
}

x-square:hover {
  background-color: black;
  /* Color change on hover */
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Dynamic Etch-A-Sketch</title>

</head>

<body>
  <button id="resize">Resize Grid</button>
  <div id="container"></div>


</body>

</html>

You could also dynamically create the canvas using JavaScript by utilizing document.createElement("canvas") at the beginning.

Answer №2

I came across an easy fix. Simply replace vh and vw with vmin. (This eliminates the need for media queries for mobile devices.)

gridContainer.style.cssText = `
            height: 95vmin;
            width: 95vmin;
            margin-top: 1vmin;
`;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the easiest way to include a copyright symbol in a React component?

I am trying to include the copyright symbol in a React component, but it doesn't seem to be working for me. function Footer() { return ( <footer> <p>&copy</p> </footer> ); } <p>&copy</p> ...

include the parent DOM element's class into its child element

I am looking to include the class of the parent DOM node in its child DOM element. For instance, let's consider the following structure: <ol class="test1"> <li> <li> <ol> I want the child ol elemen ...

How can I dynamically update the URL parameter based on the selected option in a dropdown list?

There is a single select option box with three options. When a user selects an option, the corresponding value should be appended to the URL (e.g., value=needbyDate). If another option is selected later, the previous value in the URL should be replaced w ...

Upon submission, the form is processed and 'false' is returned

Does anyone know how I can use ajax to save form data? I am encountering an issue where the page refreshes when all entries are correct. If I input any incorrect data and submit, it displays an error. However, if I then fill in all correct information, it ...

What do you call a JavaScript function when it has a name

This code is confusing to me. It's not the usual JavaScript syntax for a function that I know of. Is this a specific function? Or perhaps it's a callback for when an update event occurs? Apologies for these beginner questions, as I am quite new t ...

Display a div every 3 seconds with the help of jQuery

I am seeking a solution to display the second div (box2) every 3 seconds. Can anyone help me achieve this using jQuery? <div id="box1" style="background-color:#0000FF"> <h3>This is a heading in a div element</h3> <p>This ...

Sorting through a list of strings by checking for a specific character within each string

After spending years dabbling in VBA, I am now delving into Typescript. I currently have an array of binary strings Each string represents a binary number My goal is to filter the array and extract all strings that contain '1' at position X I ...

What is the method for selecting a specific row in a Primefaces Datatable using HtmlUnitDriver and Selenium?

Check out this code snippet: import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.htmlunit.HtmlUnitDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriv ...

Struggling with Responsiveness: Challenges with Detailed Information and Image Grid Design

Encountering challenges in achieving the desired responsiveness for a grid layout consisting of details and an image. The layout displays correctly on desktop screens, with details on the left and the image on the right. However, on mobile screens, the ima ...

Encountered a Next-Auth Error: Unable to fetch data, TypeError: fetch failed within

I've been struggling with a unique issue that I haven't found a solution for in any other forum. My Configuration NextJS: v13.0.3 NextAuth: v4.16.4 npm: v8.19.2 node: v18.12.1 When the Issue Arises This particular error only occurs in the pr ...

Delegating events after removing a class

I have a button element with the 'next' data attribute <button data-button='next' class="disabled">next</button> When I remove the disabled class to activate it, the click event doesn't trigger as expected $("[dat ...

Is it possible to alter the page color using radio buttons and Vue.js?

How can I implement a feature to allow users to change the page color using radio buttons in Vue.js? This is what I have so far: JavaScript var theme = new Vue({ el: '#theme', data: { picked: '' } }) HTML <div ...

Taking steps when a number is enclosed within a span

Testing a simple code with similar action to what I want. Apologies for any language errors, hoping to be understood :-) The HTML code snippet: <div class="pagination"> <a href="#" class=""><span>1</span></a> <a href=" ...

Organizing numerical values within for loops

I'm having trouble determining prime numbers and non-prime numbers. When I follow the logic of looping through numbers from 2 to 100, it makes sense for primes. However, when I start at 0 and loop by y + itself, it seems counterintuitive to me. For ex ...

Automatically numbering table columns with custom language localization in JavaScript using Jquery

Is there a method to automatically number table data in a local or custom language? As a Bengali individual, I have figured out how to automatically number the first data of each row using css and js. However, I am uncertain about how to implement custom n ...

Send information to the next route using Vue

Within my Vue frontend, there is a method called `moveToOrder` which asynchronously communicates with the backend to process a move from the cart collection to the orders collection: methods:{ async moveToOrder() { const res = await this.$axios.g ...

Trouble with bringing in the solana/web3.js library

After successfully importing the solana/web3.js package and running it within a NodeJS file, everything was working fine. However, things took a turn when attempting to connect this file with basic HTML, resulting in an error being thrown. import { Tra ...

Achieve full width with flexbox column wrap while minimizing the height

How can I arrange elements in columns within a container with a fixed width and variable height, when the number of elements is unknown? My challenge is that I do not know the maximum width of the child elements, preventing me from setting specific column ...

How can data be transmitted to the client using node.js?

I'm curious about how to transfer data from a node.js server to a client. Here is an example of some node.js code - var http = require('http'); var data = "data to send to client"; var server = http.createServer(function (request, respon ...

Steps to dynamically set the value of an input type="time" using JavaScript

Despite the repetitive nature of these questions, I have yet to find a solution to my specific query. Any help would be greatly appreciated. Thank you in advance. The HTML code is as follows: var start="10:30 PM"; $scope.edit={} frtime=start.split("PM ...