Im trying to create a 2 rows 3 columns puzzle using CSS and JavaScript. The idea is that the pieces of the puzzle will be all black cut in different shapes. The users has to drag the pieces to board to complete it.I wrote a javascript that creates the board and pieces. Made them draggable too but unable to proceed from here. Need help in changing the shape of pieces from square to other shapes.
var rows = 5;
var columns = 5;
var currTile;
var otherTile;
var turns = 0;
window.onload = function() {
//initialize the 5x5 board
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
//<img>
let tile = document.createElement("img");
tile.src = "blank.png";
//DRAG FUNCTIONALITY
tile.addEventListener("dragstart", dragStart); //click on image to drag
tile.addEventListener("dragover", dragOver); //drag an image
tile.addEventListener("dragenter", dragEnter); //dragging an image into another one
tile.addEventListener("dragleave", dragLeave); //dragging an image away from another one
tile.addEventListener("drop", dragDrop); //drop an image onto another one
tile.addEventListener("dragend", dragEnd); //after you completed dragDrop
document.getElementById("board").append(tile);
}
}
//pieces
let pieces = [];
for (let i = 1; i <= rows * columns; i++) {
pieces.push(i.toString()); //put "1" to "25" into the array (puzzle images names)
}
pieces.reverse();
for (let i = 0; i < pieces.length; i++) {
let j = Math.floor(Math.random() * pieces.length);
//swap
let tmp = pieces[i];
pieces[i] = pieces[j];
pieces[j] = tmp;
}
for (let i = 0; i < pieces.length; i++) {
let tile = document.createElement("img");
tile.src = "blank2.png";
//DRAG FUNCTIONALITY
tile.addEventListener("dragstart", dragStart); //click on image to drag
tile.addEventListener("dragover", dragOver); //drag an image
tile.addEventListener("dragenter", dragEnter); //dragging an image into another one
tile.addEventListener("dragleave", dragLeave); //dragging an image away from another one
tile.addEventListener("drop", dragDrop); //drop an image onto another one
tile.addEventListener("dragend", dragEnd); //after you completed dragDrop
document.getElementById("pieces").append(tile);
}
}
//DRAG TILES
function dragStart() {
currTile = this; //this refers to image that was clicked on for dragging
}
function dragOver(e) {
e.preventDefault();
}
function dragEnter(e) {
e.preventDefault();
}
function dragLeave() {
}
function dragDrop() {
otherTile = this; //this refers to image that is being dropped on
}
function dragEnd() {
if (currTile.src.includes("blank")) {
return;
}
let currImg = currTile.src;
let otherImg = otherTile.src;
currTile.src = otherImg;
otherTile.src = currImg;
turns += 1;
document.getElementById("turns").innerText = turns;
}
body {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
#board {
width: 400px;
height: 400px;
border: 2px solid purple;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
#board img {
width: 79px;
height: 79px;
border: 0.5px solid lightblue;
}
#pieces {
width: 1040px;
height: 160px;
border: 2px solid purple;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
#pieces img {
width: 79px;
height: 79px;
border: 0.5px solid lightblue;
}
<body>
<br>
<div id="board"></div>
<div id="pieces">
</div>
</body>
now, you can add event lister to the puzzle to handle dragover event with preventDefault() method to allow the drop to occur.
Then, in the event handler, you can retrieve the ID of the puzzle piece being dropped using getdata() method of the datatransfer object with following code:
boardElement.addEventListener("drop", e => {
// Get the ID of the puzzle piece being dropped
const id = e.dataTransfer.getData("text/plain");
// Find the puzzle piece
const piece = puzzlePieces.find(piece => piece.id === id);
// Update the color of the puzzle piece
piece.color = "black";
// Render the puzzle board
render();
});
Then, you can add event dragenter in drag-over class in boardelemennt and dragleave to release the drag.
Related
I'm currently doing the etch-a-sketch project of The Odin Project curriculum.
I have this event that when i click and mouseover the div, changue the background color, but I don't know how to remove this event when i release the click.
I tried using removeEventListener, tried using mouseup event but I can't figure out how to make this work.
I want to click and mouseover to draw and when i release the click stop the mouseover and stop to draw.
Another thing is that when I click in some div, this div do not change the background color immediately unless I move to another one on his side, then this other change the color.
Here is my code.
The HTML <body> only have a <div> with "grid-container" Id
JavaScript:
const divCont = document.getElementById("grid-container");
for (i = 1; i<=16; i++) {
let divCol = document.createElement('div')
divCol.classList.add("grid");
for ( j = 1; j<=16; j++){
let divRow = document.createElement('div');
divRow.classList.add("secGrid");
divCol.appendChild(divRow);
}
divCont.appendChild(divCol);
}
const hoverDivs = [...document.querySelectorAll('.secGrid')];
function colorChange(){
hoverDivs.forEach(hoverDiv => {
hoverDiv.addEventListener('click', () => {
hoverDivs.forEach(hoverDiv => {
hoverDiv.addEventListener('mouseover', () => {
hoverDiv.style.backgroundColor = "black"
});
});
});
});
}
colorChange();
CSS:
* body {
box-sizing: border-box;
padding: 0;
margin: 0;
}
#container {
max-width: fit-content;
margin: auto;
}
#grid-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width:100vh;
max-width:100%;
height:100vh;
max-height:100%;
position:relative;
background:red;
background-color: black;
}
.grid {
display: flex;
flex-direction: column;
flex-wrap: wrap;
flex-basis: 100%;
background-color: blue;
}
.secGrid {
background-color: yellow;
flex-basis: 100%;
}
I already have a solution.
I set a variable that says if it's onmousedown or not (changeColor). So if changeColor is true, onmouseover is active, if not, isn't active.
const divCont = document.getElementById("grid-container");
for (i = 1; i<=16; i++) {
let divCol = document.createElement('div')
divCol.classList.add("grid");
for ( j = 1; j<=16; j++){
let divRow = document.createElement('div');
divRow.classList.add("secGrid");
divCol.appendChild(divRow);
}
divCont.appendChild(divCol);
}
const hoverDivs = [...document.querySelectorAll('.secGrid')];
let changeColor = false;
hoverDivs.forEach(hoverDiv => {
hoverDiv.addEventListener('mousedown', () => {
hoverDiv.style.backgroundColor = "black"
changeColor=true;
});
hoverDiv.addEventListener('mouseup', () => {
changeColor=false;
});
hoverDiv.addEventListener('mouseover', () => {
if(changeColor){
hoverDiv.style.backgroundColor = "black";
}
});
});
I am a Beginner Developer and am working on a personal chess project.
I just learned how to create a drag and drop system, maybe I could learn other ways of doing It but I would like to know if there's any way to 'remove' the white background.
I don't know really how this should work but I had some ideas:
Somehow remove the white background of the ghost image.
Substitute the ghost image with the actual image being dragged.
Or just entirely remove the ghost image while dragging since we can see the piece in each square when you are dragging over it.
If it's possible to do any of these solutions it would be good!
Here is the link for the project I am working: https://codepen.io/ThalisonAmaral/full/qBYZmZq
You will be probably dealing with the function dragstart();
`
function dragstart() {
squaresDrop.forEach(square => square.classList.add('highlight'))
this.classList.add('is-dragging');
}
`
The Drag and Drop is at the end of the Js Code
Since I don't understand what I am dealing with exactly.
I searched for some possible solutions but I couldn't get any result with
DataTransfer.setDragImage().
Which I think it should be using for replacing the ghost image with an actual image but I would need to check each piece, It doesn't seem to be the way but I could be wrong.
The easiest way of doing this is by setting the opactiy of the image to 0 when you start dragging it and setting it back to 1 when dropping.
I added this.style.opacity = 0; on line 105
and this.style.opacity = 1; on line 11
Hopefully this is what you want!
/* ------- BOARD GENERATOR -------*/
const body = document.body;
const $addClass = (element,className) => {
element.classList.add(className);
};
const $setId = (element,idName)=>{element.setAttribute('id',idName)}
const $createSquare = (element,squareColor,board)=> {
element = document.createElement('div');
$addClass(element,squareColor)
$addClass(element,'square');
board.appendChild(element)
};
const $createBoardBorder = (where) => {
var board = document.createElement('div');
$addClass(board,'board');
where.appendChild(board)
}
var coordinates = [
'a8','b8','c8','d8','e8','f8','g8','h8',
'a7','b7','c7','d7','e7','f7','g7','h7',
'a6','b6','c6','d6','e6','f6','g6','h6',
'a5','b5','c5','d5','e5','f5','g5','h5',
'a4','b4','c4','d4','e4','f4','g4','h4',
'a3','b3','c3','d3','e3','f3','g3','h3',
'a2','b2','c2','d2','e2','f2','g2','h2',
'a1','b1','c1','d1','e1','f1','g1','h1'
];
function createBoard(size,lightColor,darkColor,where){
/* CREATING A DIV WITH A CLASS 'board' */
$createBoardBorder(where);
/* SELECTING THE BOARD */
var board = document.querySelector('.board');
/* GENERATING ALL THE SQUARES AND PUTTING THEM INTO THE BOARD */
var light = 'light'; var dark = 'dark';
for (let i = 0; i < 32; i++) {
$createSquare(coordinates,light,board);
$createSquare(coordinates,dark,board);
if((i+1)%4 === 0 ){
var x = light;
light = dark;
dark = x;
}
}
const squares = document.querySelectorAll('.square');
/*PUTTING ALL THE IDS IN EACH SQUARE */
for (let i = 0; i < squares.length; i++) {
$setId(squares[i],coordinates[i])
}
// ----- BOARD STYLE -----
const lightSquares = document.querySelectorAll('.light');
const darkSquares = document.querySelectorAll('.dark');
board.style.width = size+'px';
board.style.height = size+'px';
lightSquares.forEach((value,index)=>{
value.style.height = size/8+'px';
value.style.width = size/8+'px';
value.style.backgroundColor = lightColor;
darkSquares[index].style.height = size/8+'px';
darkSquares[index].style.width = size/8+'px';
darkSquares[index].style.backgroundColor = darkColor;
})
}
const boardzone = document.getElementById('boardzone');
createBoard(500,'white','rgb(64, 100, 145)',boardzone);
/*-------- PIECE RENDER --------*/
const king = document.createElement('img');
king.setAttribute('class','piece');
king.src = "https://images.chesscomfiles.com/chess-themes/pieces/neo/150/wk.png";
e1.appendChild(king)
/*-------- DRAG AND DROP --------*/
var audio = new Audio('sound.wav');
var pieces = document.querySelectorAll('.piece');
console.log(pieces);
var squaresDrop = document.querySelectorAll('.square');
pieceCheck = ()=> {
var pieces = document.querySelectorAll('.piece');
pieces.forEach(piece=>{
piece.addEventListener('dragstart',dragstart)
piece.addEventListener('drag',drag)
piece.addEventListener('dragend',dragend)
function dragstart() {
squaresDrop.forEach(square => square.classList.add('highlight'))
this.style.opacity = 0;
this.classList.add('is-dragging');
}
function drag(){
}
function dragend(){
this.style.opacity = 1;
this.classList.remove('is-dragging');
audio.play();
}
})}
pieceCheck(); //Checking if a new piece was added in the board
squaresDrop.forEach(square=>{
square.addEventListener('dragenter',dragenter);
square.addEventListener('dragover',dragover);
square.addEventListener('dragleave',dragleave);
square.addEventListener('drop',drop);
function dragenter(){
}
function dragover(){
this.classList.add('over')
//Get dragging piece
const draggedPiece = document.querySelector('.is-dragging');
this.appendChild(draggedPiece);
}
function dragleave(){
log('Leaving')
this.classList.remove('over')
}
function drop(){
}
})
body {
background-color:rgb(15,15,15);
}
.board {
display: grid;
grid-template-columns: repeat(8, 1fr);
}
#boardzone{
margin: 60px auto;
display: flex;
justify-content:center;
}
/* Drag and Drop CSS */
.piece {
height: 100%;
user-select: none;
}
.highlight {
background-color:rgba(14,14,14,0.2);
}
.is-dragging {
cursor:move;
opacity: 0.3;
transform: translate(0, 0);
}
.over{
background-color: rgba(173, 240, 118, 0.315);
}
<div id='boardzone'></div>
I want to make a background that adds and removes square divs based on the size of the container, which is affected by resizing the window.
To add the divs, I followed the examples on this post here. But, resizing the screen continues to multiply the number of divs. Is there a way to constrain the amount of squares to the size of the container, or to remove the overflow?
(I don't want to simply css overflow:hidden because that doesn't solve the problem of a billion divs being multiplied.) And I'm an absolute javascript newbie, so bear with me!
let contain = document.getElementById("squareContain");
let width = contain.offsetWidth;
let height = contain.offsetHeight;
var containerArea = width * height;
var canAdd = Math.floor(containerArea/1600); //For 40px x 40px squares
function multiplyNode(node, count, deep) {
for (var i = 0, copy; i < count - 1; i++) {
copy = node.cloneNode(deep);
node.parentNode.insertBefore(copy, node);
}
}
$(window).on("resize", function(){
multiplyNode(document.querySelector('.square'), canAdd, false);
}).resize();
Edit jsfiddle
Currently you only calculate how many squares fit once, but you need recalculate each time window size changed:
let contain = document.getElementById("squareContain");
function canAdd()
{
let square = contain.children[0],
cWidth = contain.offsetWidth,
cHeight = contain.offsetHeight,
sWidth = square.offsetWidth,
sHeight = square.offsetHeight;
return Math.floor(cWidth / sWidth) * Math.floor(cHeight / sHeight);
}
function multiplyNode(node, count, deep) {
if (contain.children.length == count)
return;
if (contain.children.length < count)
{
for (var i = 0, copy; i < count - 1; i++) {
copy = node.cloneNode(deep);
node.parentNode.insertBefore(copy, node);
}
}
else
{
while(contain.children.length > count)
{
contain.removeChild(contain.children[contain.children.length -1]);
}
}
}
$(window).on("resize", function(){
multiplyNode(contain.querySelector('.square'), canAdd(), false);
}).resize();
.square_container{
background-color: #ccc;
position: fixed;
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-content: start;
flex-wrap: wrap;
margin: 0 auto;
padding: 0 auto;
}
.square{
width: 40px;
height: 40px;
background-color: blue;
border: 1px solid red;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="squareContain" class="square_container">
<div class="square"></div><!--...etc...-->
</div>
When starting my program, everything initially runs as intended. However, when I click a button on the webpage that runs my clearBoard() function, the code in the global scope no longer runs.
I've used console.log and everything that is outside of a function is empty after running the clearBoard().
const container = document.getElementById("container");
//Create board
function makeRows(rows, columns) {
//let container = document.getElementById("container");
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', columns);
for (c = 0; c < (rows * columns); c++) {
let cell = document.createElement("div");
//cell.innerText = (c + 1);
container.appendChild(cell).className = "grid-item";
}
}
//Draw starting Board
makeRows(16, 16);
//Paint on board
const paint = document.getElementsByClassName("grid-item");
console.log(container);
for (let i = 0; i < paint.length; i++) {
paint[i].addEventListener('mouseover', function() {
this.style.backgroundColor = "black";
});
}
//Get new board size
function getNewBoard() {
//clear divs
const removeOldGrid = document.getElementById("container");
removeOldGrid.innerHTML = '';
//get input from user
let squares = prompt('How many squares per side?');
//convert input to number
let squaresInt = parseInt(squares);
//generate new board
makeRows(squaresInt, squaresInt);
}
//Clear board
function clearBoard() {
for (let i = 0; i < paint.length; i++) {
paint[i].style.backgroundColor = "";
}
getNewBoard();
}
:root {
--grid-cols: 0;
--grid-rows: 0;
--paint-color: ;
}
#container {
display: grid;
padding: 10em;
height: 40vh;
width: 50vh;
margin-left: auto;
margin-right: auto;
/*grid-gap: 1em;*/
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
}
.grid-item {
padding: 1em;
border: 1px solid #ddd;
text-align: center;
/*background-color: var(--paint-color);*/
}
/*.grid-item:hover {
background-color: black;
}
<button onclick="clearBoard()">Clear Board</button>
<div id="container">
</div>
That is happening because you are creating a new board, consequently a new grid-item element. The mouseover event listener is added to the paint variable, which contains the old element after clearBoard() is called.
The solution is to add a new event listener to paint when a new board is generated. Your JS should look something like this:
//Paint on board
var paint = document.getElementsByClassName("grid-item");
console.log(container);
// Function to add the mouseover event listener when "paint" changes
function addMouseoverEventListener() {
for (let i = 0; i < paint.length; i++)
{
paint[i].addEventListener('mouseover', function() {
this.style.backgroundColor = "black";
});
}
}
addMouseoverEventListener();
//Get new board size
function getNewBoard() {
//clear divs
const removeOldGrid = document.getElementById("container");
removeOldGrid.innerHTML = '';
//get input from user
let squares = prompt('How many squares per side?');
//convert input to number
let squaresInt = parseInt(squares);
//generate new board
makeRows(squaresInt, squaresInt);
// Get the new element
paint = document.getElementsByClassName("grid-item");
// Add the event listener again
addMouseoverEventListener();
}
Instead of using paint[i].addEventListener use window.onmouseover and check the target
const container = document.getElementById("container");
//Create board
function makeRows (rows, columns) {
//let container = document.getElementById("container");
container.style.setProperty('--grid-rows', rows);
container.style.setProperty('--grid-cols', columns);
for (c = 0; c < (rows * columns); c++) {
let cell = document.createElement("div");
//cell.innerText = (c + 1);
container.appendChild(cell).className = "grid-item";
}
}
const paint = document.getElementsByClassName("grid-item");
//Draw starting Board
makeRows(16, 16);
window.onmouseover=function(e) {
if(e.target.className == "grid-item")
{
e.target.style.backgroundColor = "black";
}
};
//Get new board size
function getNewBoard() {
//clear divs
const removeOldGrid = document.getElementById("container");
removeOldGrid.innerHTML = '';
//get input from user
let squares = prompt('How many squares per side?');
//convert input to number
let squaresInt = parseInt(squares);
//generate new board
makeRows(squaresInt, squaresInt);
}
function clearBoard() {
for (let i = 0; i < paint.length; i++) {
paint[i].style.backgroundColor = "";
}
getNewBoard();
}
:root {
--grid-cols: 0;
--grid-rows: 0;
--paint-color: ;
}
#container {
display: grid;
padding: 10em;
height: 40vh;
width: 50vh;
margin-left: auto;
margin-right: auto;
/*grid-gap: 1em;*/
grid-template-rows: repeat(var(--grid-rows), 1fr);
grid-template-columns: repeat(var(--grid-cols), 1fr);
}
.grid-item {
padding: 1em;
border: 1px solid #ddd;
text-align: center;
/*background-color: var(--paint-color);*/
}
/*.grid-item:hover {
background-color: black;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Etch-a-Sketch</title>
<meta name="author" content="">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="style.css" rel="stylesheet">
</head>
<body>
<button onclick = "clearBoard()">Clear Board</button>
<div id="container">
</div>>
<script src="script.js"></script>
</body>
</html>
I am working on a project trying to make something resembling an etch-a-sketch. I have a 780x780px square, and I am trying to get a 16x16 grid, using a series of smaller square divs.
It is on this grid that I have the hover effect. I keep getting a 15x17 grid of square divs because the last square of the row won't fit. I have margins set to 1px and padding set to 0 so I figured that to fit 16 squares on a 780px wide row, it would require me to take into account the margins (15 1px margins) and from there I could divide (780-15) by 16, the number of squares I want.
That isn't working, and the next step of this project is to have a button where the user could input any number of squares for the row/column and have either a larger or smaller squared grid STILL ON the 780x780 square. Does anyone have any ideas? I'm pretty stumped.
$(document).ready(function() {
var original = 16;
for (var y = 0; y < original * original; y++) {
$(".squares").width((780 - 15) / original);
$(".squares").height((780 - 17) / original);
$("<div class='squares'></div>").appendTo('#main');
}
$('.squares').hover(
function() {
$(this).addClass('hover');
}
)
});
function gridq() {
$('.squares').removeClass('hover');
$('div').remove('.squares');
var newgrid = prompt("How many squares on each side?");
var widthscreen = 192;
if (newgrid > 0) {
for (var x = 0; x < newgrid * newgrid; x++) {
$(".squares").width(widthscreen / newgrid);
$(".squares").height(widthscreen / newgrid);
$("<div class='squares'></div>").appendTo('#main');
}
$('.squares').hover(
function() {
$(this).addClass('hover');
}
)
}
}
#main {
height: 780px;
width: 780px;
background-color: antiquewhite;
position: relative;
}
.squares {
margin: 1px;
padding: 0;
background-color: aquamarine;
display: inline-block;
float: left;
}
.hover {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id=main>
</div>
<button onclick="gridq()">Go Again!</button>
Try this snippet? Grid initialisation is set in the grid() function and then called later when necessary. The width is set dynamically to the 16th square's right side.and the remaining squares fill out as necessary.
var wide = (780 - 15) / 16,
tall = (780 - 17) / 16; // set the square dimensions. this can be incorporated into the grid() function with 16 replaced by 'original'
function grid(x, y) {
var original = x,
y = y;
$("#main").empty(); // empty and restart
$("#main").width(wide * (original + 1));
for (var i = 0; i < original * y; i++) {
$("<div class='squares'></div>").appendTo('#main');
}
var square = $(".squares");
square.width(wide);
square.height(tall);
var side = square.eq(original - 1).position().left + square.width() + 2; // tighten the #main width
$("#main").width(side);
$('.squares').hover(
function() {
$(this).addClass('hover');
}
)
}
grid(16, 16); // starting dimension
function gridq() {
$('.squares').removeClass('hover');
$('div').remove('.squares');
var newgrid = prompt("How many squares on each side?");
var widthscreen = 192;
if (newgrid > 0) {
grid(newgrid, newgrid);
}
}
#main {
background-color: antiquewhite;
position: relative;
}
.squares {
margin: 1px;
padding: 0;
background-color: aquamarine;
display: inline-block;
float: left;
}
.hover {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id='main'>
</div>
<button onclick="gridq()">Go Again!</button>
just got beat to it...ill post this as it answers the question slightly differently and I feel is a little cleaner. Also I added in a width and a height prompt.
see the codepen here
As a side note...its good practice to make the names of your variables make sense. Also I find that breaking down your code problems into smaller more manageable chunks makes it seem less overwhelming...one step at a time :)
Enjoy and good luck!
$(document).ready(function() {
//declare the variables at the top of your functions...it enables us to change them later
var columnWidthCount = 16;
var columnHeightCount = 16;
function makeBoxes() {
//boxcount lets us set how many times we want the for loop to run...when we change the columns/rows later this variable will be updated
var boxCount = columnWidthCount * columnHeightCount;
//
for (var i = 0; i < boxCount; i++) { //loop through each box
//any code you place in here will execute each time we loop around
$("<div class='squares'></div>").appendTo('#main');
}
//we only want to declare this once so we place it after the loop
$(".squares").width((780 / columnWidthCount) - 2);
$(".squares").height((780 / columnHeightCount) - 2);
$('.squares').hover(
function() {
$(this).addClass('hover');
}
);
}
//fire the initial function
makeBoxes();
// fire function after click
$('button').on("click", function() {
$('div').remove('.squares');
var squaresHigh = prompt("How many squares high? (must be a number)");
var squaresWide = prompt("How many squares wide? (must be a number)");
//prompt returns a string...use parseInt to turn that number string into an integer
columnWidthCount = parseInt(squaresWide);
columnHeightCount = parseInt(squaresHigh);
makeBoxes();
});
});
#main {
height: 780px;
width: 780px;
background-color: antiquewhite;
position: relative;
font-size:0;
white-space:nowrap;
}
.squares {
margin: 1px;
padding: 0;
background-color: aquamarine;
display: inline-block;
float: left;
}
.hover {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id=main>
</div>
<button>Go Again!</button>