Issue
I am trying to write a program that draws squares in a size that user wants. Then it organizes the squares in the most efficient way possible. I managed already to write the program which draws the squares but as it's done in flex it will never be arranging the squares in a right way (i think?). At the moment I have the body min and max set to 1000px (to imitate 250cm width). The inputs then are multiplied by 4 to be proportional to the 1000px.
Was thinking that the best way to do it would be to write a js that creates grids and then fill it with a background colour or borders in order to be able to know which is which, rather than just drawing squares- am I thinking right? If so then my program at the moment is most likely completely useless, but was a good practice.
I would need your help to point me in the right direction.
As you see in the link- there are 3 squares and even though the 3rd square would fit next to the first it's being pushed all the way to the end of the flex box created by the biggest square. not sorted squares
document.addEventListener('DOMContentLoaded', () => {
const squares = [];
const sortedArray = [];
const [inputsOne, inputTwo] = document.getElementsByClassName('input');
const [btn] = document.getElementsByClassName('btn');
const [squaresContainer] = document.getElementsByClassName('print-content');
btn.addEventListener('click', (e) => {
e.preventDefault();
const val1 = inputsOne.value;
const val2 = inputTwo.value;
const newSquare = document.createElement('div');
newSquare.style.width = `${val1 * 4}px`;
newSquare.style.height = `${val2 * 4}px`;
newSquare.style.background = '#F2CC66';
newSquare.style.border = '1px solid grey';
newSquare.style.margin = '20px';
newSquare.setAttribute('data-width', val1);
newSquare.setAttribute('data-height', val2);
squaresContainer.appendChild(newSquare);
inputsOne.value = '';
inputTwo.value = '';
const sortSquares = () => {
let maxWidth = 300;
while (sortedArray.length === squares.length) {}
squares.forEach((el) => {});
};
});
});
body {
max-width: 1000px;
background-color: #81caec;
margin: auto;
}
form {
display: block;
text-align: center;
margin-top: 15px;
}
button,
.input {
padding: 15px;
margin-bottom: 15px;
border: none;
border-radius: 15px;
background-color: #F2CC66;
}
button:hover,
button:focus,
.input:hover {
background-color: #E88861;
}
button:focus,
.input:focus {
background: #E88861;
-webkit-box-shadow: inset 0px 0px 5px #81caec;
-moz-box-shadow: inset 0px 0px 40px #81caec;
box-shadow: inset 0px 0px 40px #81caec;
outline: none;
}
.print-content {
display: flex;
flex-wrap: wrap;
border: 1px solid none;
min-height: 60px;
max-width: 1000px;
background-color: #6EF59F;
border-radius: 15px;
}
<div class="wrapper">
<form>
<input type="number" class="input" placeholder="width cm">
<input type="number" class="input" placeholder="height cm">
<button class="btn" type="button">add square</button>
</form>
<div class="print-content"></div>
</div>
here is the code in jsfiddle https://jsfiddle.net/4t7r61sw/1/
Solution
The short answer: no, Flexible boxes will most likely not help you here.
So, CSS has a number of layout options.
Flexible boxes, to place boxes next to or below one another. Its positioning is based on columns and rows and it's a good suitor for dynamic items. But its column/row-based nature won't allow it to place boxes in the most efficient way mossible.
Grid, to place boxes based on a grid-defined layout, similar to a table, but without polluting the semantics of your HTML. It's not very well suited for dynamic items, best to use it for section elements like your navigation, content, footer, related items bar, etc.
Now, there is some talk of a masonry grid and MDN has some documentation on the topic as well, but that'll take some more time before all modern browsers support it.
Floats, to be used for showing some pictures along with paragraphs of text. This was misused a lot in the olden days for defining entire layouts as there were no proper alternatives.
Absolute/relative positioning. Simply use
top,left, etc. to define the exact pixels where a box should go.
So unfortunately, a "most efficient" positioning technique, the masonry layout or "bin packing" as @Terry mentioned, simply isn't supported natively yet. You'll have to go for a custom implementation that most probably will use absolute positioning to define to exact pixels for each box. Pinterest uses this technique too, by the way.
Thankfully though, you're not the only or first one that has encountered this issue. Searching for "bin packing css", I came across this CodePen by Brian Gonzalez which gives an impression of the algorithm that needs to be written. There are also a few more published options available, like <bin-packing-grid> or the <canvas>-based potpack. Searching for "masonry css" has lots of helpful results as well, the established masonry library by David DeSandro, for example.
Answered By - J.P. ten Berge
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.