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.
Image
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>
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>
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>
Related
I'm trying to align a top menu which consists of 3 blocks of content.
What I'm trying to achieve is this:
block 1: left aligned
block 2: centered horizontally
block 3: right aligned
If all 3 blocks were the same size, I could use flexbox (as in the snippet), but they're not, so it doesn't produce the output I require.
Instead, flexbox puts equal space between the 3 blocks - resulting in the middle block being aligned off-center.
I was wondering if this could be achieved with flexbox, or if not, another solution. This needs to work robustly in production so a 'Grid' solution is not applicable as there is insufficient support.
.container {
margin: 20px 0;
}
.row {
background-color: lime;
display: flex;
justify-content: space-between;
}
.item {
background-color: blue;
color: #fff;
padding: 16px;
}
<div class="container">
<div class="row">
<div class="item">left, slightly longer</div>
<div class="item">center, this item is much longer</div>
<div class="item">right</div>
</div>
</div>
You can consider flex-grow:1;flex-basis:0% for the left and right elements then use text-align to align content inside. I have added an extra wrapper to keep the background only around the text.
The trick is to calculate the free space by removing only the middle content and split it equally to the left and right element.
.container {
margin: 20px 0;
padding-top:10px;
background:linear-gradient(#000,#000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:last-child {
text-align: right;
}
.item span{
background-color: blue;
display:inline-block;
padding: 16px;
border: 2px solid red;
box-sizing:border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
You can also do the same by keeping the element close. Simply adjust text-align:
.container {
margin: 20px 0;
padding-top: 10px;
background: linear-gradient(#000, #000) center/5px 100% no-repeat; /*the center*/
}
.row {
background-color: lime;
display: flex;
color: #fff;
}
.item:not(:nth-child(2)) {
flex-basis: 0%;
flex-grow: 1;
}
.item:first-child {
text-align: right;
}
.item span {
background-color: blue;
display: inline-block;
padding: 16px;
border: 2px solid red;
box-sizing: border-box;
}
<div class="container">
<div class="row">
<div class="item"><span>left, slightly longer</span></div>
<div class="item"><span>center, this item is much longer</span></div>
<div class="item"><span>right</span></div>
</div>
</div>
I asked what seems to be a very similar question and stack overflow directed me here. The response from #Paolamoralesval inspired me to realise the required effect can be achieved in CSS grid. Now that grid support is pretty much universal I hope that this meets everyone's needs. This solution is I believe fully responsive to window size as well as height and width of the header items as you should see if you resize the window where you view the snippet.
.header {
grid-row: 1;
grid-column: 1;
display: grid;
grid-template-rows: min-content;
grid-template-columns: 1fr 1fr 1fr;
}
.header-left {
justify-self: start;
align-self: center;
text-align: left;
background-color: red;
}
.header-center {
justify-self: center;
align-self: center;
text-align: center;
background-color: green;
}
.header-right {
justify-self: end;
align-self: center;
text-align: right;
background-color: blue;
}
.shrink-kitty {
width: 200px;
}
<html>
<body>
<div class="page">
<div class="header">
<div class="header-left">
<img class="shrink-kitty" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Kittyply_edit1.jpg/1280px-Kittyply_edit1.jpg"/><br/>
By David Corby<br/>
Edited by: Arad<br/>Image:Kittyplya03042006.JPG<a><br/><a href="https://creativecommons.org/licenses/by/2.5" title="Creative Commons Attribution 2.5">CC BY 2.5, Link
</div>
<div class="header-center">In the middle</div>
<div class="header-right">
Much much much much more on the right hand side</br>
Indeed two lines
</div>
</div>
<div class="body">Body of the page</div>
<div class="footer">At the bottom</div>
</div>
</body>
</html>
can you give flex-grow:1 for the item class and check
.item {
background-color: blue;
color: #fff;
padding: 16px;
flex-grow:1;
}
Hope this is what you are looking for
Alternative using display table (an ancient supported grid).
Quote from https://www.w3schools.com/cssref/pr_tab_table-layout.asp
If no widths are present on the first row, the column widths are divided equally across the table, regardless of content inside the cells
.container {
display: table;
table-layout: fixed
} // would divide cells equally along table's 100% width.
.row {
display: table-row
}
.item {
display: table-cell
}
I've got three div's that I'd like to arrange like this
My code should look like this :
<div class="container">
<div class="div1">Div #1</div>
<div class="div2">Div #2</div>
<div class="div3">Div #3</div>
</div>
So - what should my css / html be if at all possible to do?
.container {
display: flex; /* establish flex container */
flex-direction: column; /* align children (flex items) vertically */
flex-wrap: wrap;
height: 120px;
}
.container > div {
flex: 1 0 50px; /* occupy free space, don't shrink, initial height */
width: calc(50% - 10px); /* half container size less margins */
margin: 5px;
box-sizing: border-box;
border: 1px solid black;
}
<div class="container">
<div class="div1">Div #1</div>
<div class="div2">Div #2</div>
<div class="div3">Div #3</div>
</div>
Benefits of flexbox:
minimal code; very efficient
centering, both vertically and horizontally, is simple and easy
equal height columns are simple and easy
multiple options for aligning flex elements
it's responsive
unlike floats and tables, which offer limited layout capacity because they were never intended for building layouts, flexbox is a modern (CSS3) technique with a broad range of options.
To learn more about flexbox visit:
Methods for Aligning Flex Items
Using CSS flexible boxes ~ MDN
A Complete Guide to Flexbox ~ CSS-Tricks
What the Flexbox?! ~ YouTube video tutorial
Browser support:
Flexbox is supported by all major browsers, except IE 8 & 9. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. For a quick way to add all the prefixes you need, use Autoprefixer. More details in this answer.
<style type="text/css">
.main{
height:500px;
width:400px;
}
div.subDiv{
height:50%;
margin:5px;
}
div.subDiv>div{
width:47%;
height:100%;
display:inline-block;
}
div.subDiv>div>div{
height: 122.5px;
background-color:gray;
}
div.subDiv>div>div+div{
margin-top:5px
}
.gray{
background-color:gray;
}
</style>
<div class="main">
<div class="subDiv">
<div>
<div></div>
<div></div>
</div>
<div class="gray"></div>
</div>
</div>
Try this.
To achieve your expected result, use following option
.container {
height: 100px;
}
.div1 {
float: left;
postion: absolute;
width: 20%;
border: 1px solid black;
height: 50%;
}
.div2 {
float: left;
clear: both;
vertical-align: bottom;
width: 20%;
border: 1px solid black;
height: 50%;
}
.div3 {
display: inline-block;
width: 20%;
height: 100%;
border: 1px solid black;
}
http://codepen.io/nagasai/pen/KMWgEz
I need to convert a 3-column fixed width layout to a responsive one and have been frying my brain trying to understand all the various ways people are going about this. The column widths are roughly 22% - 56% - 22% of the container div width. When displaying in a smartphone context, I want columns 1 and 3 to appear together side by side taking up 50% of the screen width each, then column 2 (the main content) to appear below at 100% of width.
Can anyone advise the best way to go about achieving this? Do I need to swap columns 2 and 3 around to get them to flow the way I want them to? Or is there another way that works as well without having to go through and change the markup of the entire site? I would like to use CSS only solutions if possible. Thanks.
You can do this with media queries and floats. Using float: left and float: right you just need to set up your HTML properly. The trick is to float column 1 to the left and two and three to the right with three coming before two in your html:
FIDDLE
HTML
<div class="wrapper">
<div class="one"></div>
<div class="three"></div>
<div class="two"></div>
</div>
CSS
.one{
float: left;
background: red;
width: 22%;
height:100px;
}
.two{
float: right;
background: blue;
width: 56%;
height:100px;
}
.three{
float: right;
background: green;
width: 22%;
height:100px;
}
#media only screen and (max-width: 300px){
.one{
width: 50%
}
.two{
width: 100%
}
.three{
width: 50%
}
}
UPDATE
As Crispy-George posted you could use flexbox but it does have limited browser support and basically doesn't work with IE 9 and below:
FLEXBOX EXAMPLE
If you have to maintain a strict order on your columns, like:
<div class='box box-1'>Small box</div>
<div class='box box-2'>Yeah, I'm the big box</div>
<div class='box box-3'>Even Smaller box</div>
you can use flexbox to change the order of these boxes on your desired screen resolutions, however I believe it has no support for lower than IE9, but if you dont have to support older browsers, check out the demo here.
The markup:
<div class='container'>
<div class='box box-1'>Small box</div>
<div class='box box-2'>Yeah, I'm the big box</div>
<div class='box box-3'>Even Smaller box</div>
</div>
And the css stuff:
.container{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.box{
min-height: 200px;
font-size: 18px;
}
.box-1{
width: 25%;
background: red;
}
.box-2{
width: 60%;
background: teal;
}
.box-3{
width: 15%;
background: cyan;
}
#media all and (max-width: 768px){
.box-1{
-webkit-order: 1;
-ms-order: 1;
order: 1;
width: 50%;
}
.box-3{
-webkit-order: 2;
-ms-order: 2;
order: 2;
width: 50%;
}
.box-2{
-webkit-order: 3;
-ms-order: 3;
order: 3;
width: 100%;
}
}
Let's say I have a div, 100px wide, and a variable number (from 1 to 6) of elements, 10px wide, inside that div.
How can I equally space them so that:
if there is 1 element inside, there will be no additional spacing
if there are from 2 to 6 elements, spacing between each would be 80px (for 2), 35px (for 3), 20px (for 4), etc...
The first item will always be placed at the most left position, without padding, and the last item will always be placed at the most right position, also without padding.
I'm not concerned about IE, so this could be CSS3. Anyways, I am concerned about javascript. I know this would be a 1 liner in JS, but I certainly want to avoid it if possible, so please refrain answering if you're going to post a JS solution.
Regards
Edit:
Example: http://codepen.io/anon/pen/wbiFA
HTML
<div class="container">
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
</div>
CSS:
.container {
width: 900px;
border: 1px solid red;
display: flex;
justify-content: space-between;
height: 50px;
}
.item {
border: 1px solid blue;
flex-basis: auto;
width: 171px
}
Ok, did it :)
You don't need CSS3 features like flexible boxes. The following CSS2.1 features are enough:
text-align:justify
display: inline-block
::after pseudo-element
.container {
width: 900px;
border: 1px solid red;
height: 50px;
text-align: justify;
}
.container:after {
content: '';
width: 100%;
display: inline-block;
}
.item {
border: 1px solid blue;
width: 171px;
height: 100%;
display: inline-block;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Using Flexbox i managed a close enough result:
http://codepen.io/coljung/pen/bufmh
.container {
border: 1px solid red;
width:1000px;
height:100px;
display: flex;
justify-content: space-around;
}
.item {
border: 1px solid blue;
background:red;
width:100px;
height:100%;
}
Now, it doesnt achieve the exact padding you are looking for. In that case you have to do it manually for every single case.
My issue is that I have two (or more) divs of the same class, that need to be spaced from each other. I cannot directly use margins however, as the last or first element would also have the margin applied, which I do not want.
-Green is where I want the space
-Red is where I don't want it
As the only solutions I can think of are complicated / involve hard-coding a value, I am hoping that someone can think of a clever, simple solution to this problem.
Details: Sometimes these divs would be by themselves, and on a rare occasion floated.
Any advice on how above ideas could be better, any new ideas, or just help in general would be greatly appreciated ;)
You can try something like the following:
h1{
margin-bottom:<x>px;
}
div{
margin-bottom:<y>px;
}
div:last-of-type{
margin-bottom:0;
}
or instead of the first h1 rule:
div:first-of-type{
margin-top:<x>px;
}
or even better use the adjacent sibling selector. With the following selector, you could cover your case in one rule:
div + div{
margin-bottom:<y>px;
}
Respectively, h1 + div would control the first div after your header, giving you additional styling options.
If you don't require support for IE6:
h1 {margin-bottom:20px;}
div + div {margin-top:10px;}
The second line adds spacing between divs, but will not add any before the first div or after the last one.
Why not use margin? you can apply all kinds off margins to an element. Not just the whole margin around it.
You should use css classes since this is referencing more than one element and you can use id's for those that you want to be different specifically
i.e:
<style>
.box { height: 50px; background: #0F0; width: 100%; margin-top: 10px; }
#first { margin-top: 20px; }
#second { background: #00F; }
h1.box { background: #F00; margin-bottom: 50px; }
</style>
<h1 class="box">Hello World</h1>
<div class="box" id="first"></div>
<div class="box" id="second"></div>
Here is a jsfiddle example:
http://jsfiddle.net/baXmu/2/
REFERENCE:
http://www.html.net/tutorials/css/lesson10.php
DIVs inherently lack any useful meaning, other than to divide, of course.
Best course of action would be to add a meaningful class name to them, and style their individual margins in CSS.
<h1>Important Title</h1>
<div class="testimonials">...</div>
<div class="footer">...</div>
h1 {margin-bottom: 0.1em;}
div.testimonials {margin-bottom: 0.2em;}
div.footer {margin-bottom: 0;}
A slightly newer solution to this problem is to put the divs in a container that is display: flex or display: grid and to use the gap css property which will only add a space between elements inside the container, but not before/after.
flex solution:
.wrapper {
display: flex;
flex-direction: column;
gap: 20px;
}
header, footer {
background: red;
color: white;
}
<header>header</header>
<div class="wrapper">
<div>section 1</div>
<div>section 2</div>
<div>section 3</div>
</div>
<footer>footer</footer>
grid solution:
.wrapper {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
header, footer {
background: red;
color: white;
}
<header>header</header>
<div class="wrapper">
<div>section 1</div>
<div>section 2</div>
<div>section 3</div>
</div>
<footer>footer</footer>