This question already has answers here:
Image inside div has extra space below the image
(10 answers)
Why does my image have space underneath?
(3 answers)
Align inline-block DIVs to top of container element
(5 answers)
Closed 3 years ago.
I am trying to create a chess board.I am using nested loops to do that. The problem is that there is a gap between two horizontal rows of the block. Below I have create a snippet for 3x3 board.
const board = document.querySelector('#board');
const colors = ["black","gray"]
function start(){
for(let i = 0;i<3;i++){
let br = document.createElement('br')
for(let j = 0;j<3;j++){
let block = document.createElement('div');
block.classList.add('block');
let id = (i * 8) + j
block.id = id;
block.style.backgroundColor = colors[(id+i) % 2]
board.appendChild(block)
}
board.appendChild(br)
}
}
start()
.block{
height: 70px;
width: 70px;
display:inline-block;
}
<div id="board"></div>
I already head about solution using float:left instead of display:inline-block. How could I remove the gap?
I would also like to see if there is better code for creating chessboard?
The gap is there because the <br>. #board { font-size: 0; } will remove it.
You seem to be trying to create a table with divs. It's perfectly fine, apart from the fact that you'll need to manage spaces between the blocks with margins, if you ever need them.
You could create a table and use border-collapse: collapse
const board = document.querySelector('#board');
const colors = ["black", "gray"]
function start() {
for (let i = 0; i < 3; i++) {
let tr = document.createElement('tr')
for (let j = 0; j < 3; j++) {
let block = document.createElement('td');
block.classList.add('block');
let id = (i * 8) + j
block.id = id;
block.style.backgroundColor = colors[(id + i) % 2]
tr.appendChild(block)
}
board.appendChild(tr)
}
}
start()
.block {
height: 70px;
width: 70px;
}
#board {
border-collapse: collapse;
}
<table id="board"></table>
try to use flex
function start(n){
let s='';
for(let i = 0;i<n;i++){
s+='<div class="row">'
for(let j = 0;j<n;j++){
s+=`<div class="block ${(i+j)%2?'white':''}"></div>`
}
s+='</div>'
}
board.innerHTML=s;
}
start(3)
.block{ height: 70px; width: 70px; background: black }
.white { background: gray }
.row { display: flex }
<input type="range" min="1" max="8" oninput="start(this.value)" value=3 /><br>
<div id="board"></div>
I'd recommend using canvas. You can fill the screen with rectangles, each with sidelength width ,and starting position (i*width,j*width). Each rect can be filled with a colour, by specifying the fill colour before drawing. Look into a good HTML Canvas tutorial.
Related
I'm working on a drum machine and I am not sure how to approach making the squares clickable. How can I alter the color of a specific square to crimson upon being clicked?
const drums = ["Crash", "CHiHat", "OHiHat", "Tom3", "Tom2", "Tom1", "Snare", "Kick"];
for (let i = 0; i < 8; i++) {
for (let v = 0; v < 16; v++) {
var block = document.getElementById('canvas');
var context = block.getContext('2d');
context.strokeRect(100 + (55 * v), (55 * i), 50, 50);
context.fillStyle = 'crimson';
context.fillRect(100 + (55 * v), (55 * i), 50, 50);
}
}
<canvas id="canvas" width="1920" height="1080"></canvas>
I tried addEventListener, but that returned an error.
A canvas is just a grid of pixels. You can't assign a click handler to a canvas shape, because that shape is just some pixels. If you aren't restricted to using canvas, try using regular elements, like this:
var drumMachine = document.getElementById("drumMachine");
var nRows = 8;
var nCols = 16;
for (let i = 0; i < nRows; i++) {
var row = document.createElement("tr");
for (let j = 0; j < nCols; j++) {
let cell = document.createElement("td");
cell.className = "clickable";
cell.addEventListener("click", function () {
this.classList.toggle("activated");
});
row.appendChild(cell);
}
drumMachine.appendChild(row);
}
#drumMachine {
margin-left: 100px;
}
.clickable {
width: 50px;
height: 50px;
background-color: black;
cursor: pointer;
margin-right: 5px;
margin-bottom: 5px;
display: inline-block;
}
.clickable.activated {
background-color: crimson;
}
<table id="drumMachine"></table>
This does a few things.
First, it defines the grid dimensions and then creates the elements in a two-dimensional loop.
It then adds an click event listener to each element (here is where HTML elements shine against HTML canvas!)
After which, the elements are assembled into a regular table setup. CSS is used to mimic your canvas setup.
If you have any questions don't hesitate to ask in the comments.
I am looking for hints on how to tackle the visualisation of a storage container and its content.
The box has to have a fixed number of cells (9x9) which are permanently displayed
I retrieve the count of items from a SQL database (currently via SUM(item_count) )
Each item should be represented by a fixed image in a cell of the box, i.e. if the SQL query returns 15 items, the first 15 cells of my grid/table should each display my image
Should I use a html table or a CSS grid to visualize my box?
An entirely different solution?
What is the best way to iterate through the cells to append the image?
Amongst other things I have unsuccessfully tried to iterate through a css grid via:
// numberOfItems comes from SQL query and is defined previously
function generateItems() {
for(i=0; i < numberOfItems; i++) {
var addItemsHere = document.getElementById("id_" + i);
var items = document.createElement("img");
items.src = "item.png";
addTubesHere.appendChild(items);
}
}
If you couldn't tell I am very new to the topic and happy to read through documentation but I hope to get some pointers into the right direction.
Thanks!
It doesn't sound as though your data has the semantics of a table but it does sound like a grid.
This snippet uses Javascript to create a 9x9 grid, putting cells in as div elements.
Rather than add a further (img) element the images in the first n cells are set by using background-image on the cell-divs. You could change this to actually create another element (an img) and set the src but from what is in the question as it stands this doesn't seem necessary.
//SET UP THE GRID
const box = document.querySelector('.box');
const numberOfItems = 15; //set just for this demo
for (let row = 0; row < 9; row++) {
for (let col = 0; col < 9; col++) {
let cell = document.createElement('div');
cell.classList.add('cell');
box.appendChild(cell);
}
}
//NOW PUT THE IMAGES INTO THE FIRST N CELLS
const cells = box.querySelectorAll('.cell');
for (let i = 0; i < numberOfItems; i++) {
cells[i].style.setProperty('--bg', 'url(https://picsum.photos/id/1015/200/200)');
}
.box {
width: 100vmin;
height: 100vmin;
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(9, 1fr);
gap: 1vmin;
}
.box>* {
border: 0.1vmin solid;
background-image: var(--bg);
background-size: cover;
background-position center center;
}
<div class="box"></div>
You can use background repeat, like this:
<style>
div {
background-image: url("https://www.i2clipart.com/cliparts/7/5/7/8/clipart-rick-astley-64x64-7578.png");
background-size: 64px 64px;
width: 64px;
height: 64px;
}
</style>
<div id="ricks"></div>
<script>
let ricks = document.getElementById('ricks');
ricks.style.width = (4 * 64) + 'px';
ricks.style.height = (3 * 64) + 'px';
</script>
jsfiddle example
I am currently doing the odin project Etch-A-sketch challenge.
I currently have it so that using JavaScript I create 16 row divs, with 16 grid squares inside each row div. So it is a 16 x 16 grid.
How do I make it so that when I put more grid squares into the container the whole grid stays the same size and the gird squares get smaller or larger in the container without it spilling over the container walls with flexbox?
Here is my codepen: https://codepen.io/Alex-Swan/pen/jOyMwzm
Javascript:
/* This function creates 16x16 grid or what ever input the user has given, the event listner at the
bottom of the function makes it that when a user hovers over a grid square it turns black.
*/
function fullGrid(e) {
for (let i = 0; i < e; i++) {
row = document.createElement("DIV");
container.appendChild(row);
row.className = "row";
for (let i = 0; i < e; i++) {
square = document.createElement("DIV");
row.appendChild(square);
square.className = "gridSquare";
}
}
for (let i = 0; i < gridSquare.length; i++) {
gridSquare[i].addEventListener("mouseover", () => {
gridSquare[i].className += " squareBlack";
});
}
}
CSS:
.container {
border: black solid 1px;
width: 400px;
height: 400px;
}
.row {
display: flex;
height: 6%;
}
.gridSquare {
border: #444242 solid 1px;
margin: auto;
height: 100%;
width: 33.3%;
}
.squareBlack {
background-color: black;
}
Fixed it!
In JavaScript I calculated to height by dividing the GridSquare amount by the 400px size of the container. Also i changed the CSS box-sizing to border box.
Javascript:
function fullGrid(e) {
for (let i = 0; i < e; i++) {
row = document.createElement("DIV");
container.appendChild(row);
row.className = "row";
for (let i = 0; i < e; i++) {
square = document.createElement("DIV");
row.appendChild(square);
square.className = "gridSquare";
square.style.width = "100%"; // <----- HERE
let height = 400 / parseInt(squareAmount); // <----- HERE
square.style.height = `${height}px`; // <----- HERE
}
}
for (let i = 0; i < gridSquare.length; i++) {
gridSquare[i].addEventListener("mouseover", () => {
gridSquare[i].className += " squareBlack";
});
}
}
I am working on an Etch-A-Scetch project. I created grid which contains a certain amount of squares of the same size (the user is able to type in the amount of squares which should be displayed). To create the squares I used CSS grid and a Javascript for loop. Now I want to add event listeners, which change the background of each Square when moving over it. Unfortunately, it always shows errors when I try to add some. The current code doesn't show an error, it just doesn't do anything.
The method createSquares() should just create and add the amount of squares to the DOM. The user types in an amount, for example 10, and the displayed squares are 10 in x-direction and 10 in y-direction --> makes 100 squares in total. After that I want to add an event listener, which changes the background color of the square the user hovers over (the background color should stay changed). I am thankful for any help, because I'm really clueless :D
let squareDiv = document.querySelector('.squareDiv');
let squares = document.getElementById('#squares')
let squareAmount = 10;
function blackColor() {
this.style.backgroundColor = '#000';
this.style.border = '0px';
}
function createSquares() {
for (i = 0; i < squareAmount * squareAmount; i++) {
squares = document.createElement('div');
squares.setAttribute("id", "squares");
// squares.setAttribute("onmouseover", "addEventListener")
squares.style.display = 'grid';
squareDiv.style.setProperty('--columns-amount', squareAmount);
squareDiv.style.setProperty('--rows-amount', squareAmount);
squareDiv.appendChild(squares);
}
}
createSquares();
if (squares) {
squares.addEventListener('mouseover', _ => {
squares.style.backgroundColor = blackColor;
});
}
<div class="squareDiv"></div>
<div id="squares"></div>
You likely need something like this
I fixed the script, now fix the CSS
let container = document.getElementById("container")
let squareAmount = 5;
function getRandom() {
return '#'+Math.floor(Math.random()*16777215).toString(16);
}
function colorIt(sq) {
sq.style.backgroundColor = document.getElementById("random").checked? getRandom() : '#000';
sq.style.border = '0px';
}
function createSquares() {
let grid = document.createElement('div');
grid.setAttribute("id","squares")
grid.classList.add("grid");
for (i = 0; i < squareAmount * squareAmount; i++) {
square = document.createElement('div');
square.classList.add("square");
grid.appendChild(square);
}
container.innerHTML="";
container.appendChild(grid)
}
createSquares();
container.addEventListener('mouseover',
e => {
const target = e.target;
if (target.matches(".square")) colorIt(target)
}
);
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
grid-auto-rows: 1fr;
}
.grid::before {
content: '';
width: 0;
padding-bottom: 100%;
grid-row: 1 / 1;
grid-column: 1 / 1;
}
.grid > *:first-child {
grid-row: 1 / 1;
grid-column: 1 / 1;
}
/* Just to make the grid visible */
.grid > * {
background: rgba(0,0,0,0.1);
border: 1px white solid;
}
<label><input type="checkbox" id="random" />Random</label>
<div id="container"></div>
You have already created the element in DOM, please remove this.
while creating the element using function createSquares assign class instead of ID. Since, you should have only element with one ID.
Move the addEventListener inside the function after you have created the element.
When creating similar html elements with same properties it is better to group them together with class and not id. This is good because it becomes simple to loop these html elements with forEach or other looping methods you may prefer.
let squareDiv = document.querySelector('.squareDiv');
let squares = document.getElementById('#squares')
let squareAmount = 10;
function blackColor() {
this.style.backgroundColor = '#000';
this.style.border = '0px';
}
function createSquares() {
for (i = 0; i < squareAmount * squareAmount; i++) {
squares = document.createElement('div');
squares.setAttribute("class", "squares");
squares.setAttribute("style", "width: 100px; height: 100px; background: #090; margin-bottom: .3rem;");
// squares.setAttribute("onmouseover", "addEventListener")
squares.style.display = 'grid';
squareDiv.style.setProperty('--columns-amount', squareAmount);
squareDiv.style.setProperty('--rows-amount', squareAmount);
squareDiv.appendChild(squares);
}
}
createSquares();
if (squares) {
squares.addEventListener('mouseover', _ => {
squares.style.backgroundColor = blackColor;
});
}
<div class="squareDiv"></div>
<div id="squares"></div>
This question already has answers here:
Align inline-block DIVs to top of container element
(5 answers)
CSS inline-block wrap issue with mixed text and empty div
(2 answers)
Closed 4 years ago.
Jsfiddle showing the issue: Fiddle
I have a few divs and inside they hold other divs (both created from js),
and an Event handler that shows text ('innerText') when clicked,
my problem is, the event handler makes the whole inner div to drop down, what is causing it?
HTML
<div class="container">
<div id="board"></div>
</div>
scc
.square{
height: 100%;
width: 50px;
border: 1px solid black;
display: inline-block;
padding-top: 2.3%;
box-sizing: border-box;
text-align: center
}
.row{
height: 50px;
width: 500px;
}
js
/* creating state */
var cellsArr = [];
var cell = {state: 'clean', dangerScale:0}
for(i=0;i<100 ; i++){
var cell = {state: 'clean', dangerScale:0};
cellsArr.push(cell)
}
var ranArr = [], bomNum = 20;
for(i=0; i<bomNum; i++){
ran = Math.floor(Math.random()*100);
ranArr.push(ran)
}
for(i=0; i<ranArr.length; i++){
cellsArr[ranArr[i]].state = 'dirty'
}
/* creating the dom */
var id = 0
for (var i = 0; i <= 9; i++) {
var divRow = document.createElement('div')
divRow.classList.add('row')
for (var j = 0; j <= 9; j++) {
var div = document.createElement('div')
div.classList.add('square')
div.id = id
div.style.cursor = 'pointer';
div.addEventListener('click',show)
id ++
divRow.appendChild(div)
}
document.getElementById("board").appendChild(divRow)
}
function show(ev){
ev.target.innerText = cellsArr[ev.target.id].state;
}