Reputation: 79
I am trying to create a set of div that look like like the following image. I can make them all to stay next to each other but I cannot make the small one above the other one. Unless I make a parent div for them which I prefer to see if there is a better method for that.
Here is the code: Fiddle
div.boxes{
width:450px;
height:100px;
border:1px solid #fff;
background:#000;
float:left;
}
div.boxes > div{
background:#bf00bd;
border:1px solid #999;
}
div.boxes > div.item1{
width:50px;
height:50px;
float:left;
}
div.boxes > div.item2{
width:100px;
height:20px;
float:left;
}
div.boxes > div.item3{
width:100px;
height:20px;
float:left;
}
div.boxes > div.item4{
width:50px;
height:50px;
float:right;
}
div.boxes > div.item5{
width:50px;
height:50px;
float:right;
}
div.boxes > div.item6{
width:50px;
height:50px;
float:right;
}
<div class="boxes">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
<div class="item4"></div>
<div class="item5"></div>
<div class="item6"></div>
</div>
Upvotes: 3
Views: 135
Reputation: 740
If you plan to build your elements dimensions with absolute units (as in your exemple), rather than using relatives units (as %
or em
) and if you really (really) don't want to define another container inside your .boxes
element, and if you need to target old browsers, you can use absolute positioning.
Be careful, that positioning is not recommended, because it makes hard (or impossible) to correctly use responsive web design style with it.
Elements that are relatively positioned remain in the normal flow of the document. In contrast, an element that is absolutely positioned is taken out of the flow; thus, other elements are positioned as if it did not exist. The absolutely positioned element is positioned relative to its nearest positioned ancestor (i.e., the nearest ancestor that is not static).
Using this technique, you will be able to locate precisely where you want to pin items (relative to an ancestor and not it previous sibling). So, use top / bottom
and left / right
properties in order to pin elements from a positioned ancestor. As exemple, top: 5px
will pin the element from 5px of the top of first positioned ancestor (with absolute or relative
). You can set those properties using pixel, percentage or all other units that you need.
So, to answer your question, this exemple I have written bellow is made in order to give a way to achieve your goal, but I don't recommend to use it... You definitely should create another div in order to wrap items you want one above the other.
:root {
--boxes-width: 450px;
--boxes-height: 100px;
--item-padding: 10px;
--item-width: 50px;
}
.boxes {
position: relative;
width: var(--boxes-width);
height: var(--boxes-height);
border:1px solid #fff;
background:#000;
float:left;
}
.item {
position: absolute;
background:#bf00bd;
border:1px solid #999;
top: var(--item-padding);
}
.item:first-child {
width:var(--item-width);
height:calc(var(--boxes-height) - var(--item-padding) * 2);
left: var(--item-padding);
}
.item:nth-child(2),
.item:nth-child(3) {
width: calc(var(--item-width) * 2);
height:calc((var(--boxes-height) - var(--item-padding) * 2) / 2 - (var(--item-padding) / 2));
left: calc(var(--item-width) + (var(--item-padding) * 2));
}
.item:nth-child(3) {
top: calc(var(--boxes-height) / 2 + (var(--item-padding) / 2));
}
.item:nth-child(n+4) {
position: relative;
float: right;
width: var(--item-width);
height: calc(var(--boxes-height) - var(--item-padding) * 2);
margin-right: var(--item-padding);
}
<div class="boxes">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Actually, even if this technique is not recommended in many cases, it can suits your needs. And sometimes, absolute positioning is the best thing to do. It depends on your goals, on the flexibility the code give you and the browsers you want to target. There is no standard way to do things or not, because there is nothing inherently wrong with using absolute positioning. Nevertheless, there are most common usages to make your code easier to maintain and more optimized for accessibility across usages.
In your case, I think you may wrap the items you want one above the other by a parent div
. Actually, div
elements have been created in order to give the possibility to merge some code in a special layout. It's not a bad practice to make use of a div
as a container inside others div
wrappers. But you should avoid using useless wrapper when it's not needed because it slows down rendering, DOM, CSSOM relations and make your code harder to read (among other issues). You are the only one who can judge if it's necessary or not. In a nutshell, using one or two wrappers is definitely not a bad practice.
So, depending on browsers you target, a good way to achieve it could be:
I updated my answer to give you more tips in order to let you understand your options. As you used float system in your exemple, I wrote a code that used it as well and that is compliant for many (and old) browser.
The following code can be optimized to follow your needs, I reused your code as you wrote it. Also, I voluntary used float
system rather than grid
or flexbox
system in order to target the most browsers as possible. Keep in mind that grid system is another (really) good and modern approach to reduce code, but it won't work in every browser for now. As coded in another answer, grid
layout is powerful that you should think about. Especially because all modern browsers can use it.
.boxes{
position: relative;
width: 100%;
max-width: 450px;
height: 100px;
border:1px solid #fff;
background:#000;
float:left;
padding: 10px;
box-sizing: border-box;
}
.box {
height: 100%;
}
.box--left{ float: left }
.box--left > .item { float: left; }
.box--right{ float: right }
.box--right .item:last-child { margin-right: 0; }
.box-vert {
width: 100px;
float: left;
}
.box-vert .item {
height: calc(50% - 5px);
width: 100%;
}
.item{
background:#bf00bd;
border:1px solid #999;
width: 50px;
height: 100%;
margin-right: 10px;
display: inline-block;
}
<div class="boxes">
<div class="box box--left">
<div class="item"></div>
<div class="box box-vert">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
<div class="box box--right">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
Upvotes: 4
Reputation: 1594
You can always use CSS grid
there would be no need for positioning absolute, parent div wrappers and you can make it as flexible as you want.
.boxes{
display: grid;
border:1px solid #fff;
background:#000;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 10px;
grid-row-gap: 5px;
height: 150px;
}
.boxes > div{
background:#bf00bd;
border: 1px solid #fff;
}
.item1{
grid-row: 1/3;
grid-column: 1/2;
}
div.boxes > div.item2{
grid-row: 1/2;
grid-column: 2/3;
}
div.boxes > div.item3{
grid-row: 2/3;
grid-column: 2/3;
}
div.boxes > div.item4{
grid-row: 1/3;
grid-column: 4/5;
}
div.boxes > div.item5{
grid-row: 1/3;
grid-column: 5/6;
}
div.boxes > div.item6{
grid-row: 1/3;
grid-column: 6/7;
}
<div class="boxes">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
<div class="item4"></div>
<div class="item5"></div>
<div class="item6"></div>
</div>
Upvotes: 1