DIVs float in a non-linear way - html

have a css float problem that i'm not sure how to fix or best way to fix and can't seem to find anything in searches. I have a variable amount of items to show inside a div, using a css float left on all the inner boxes (1, 2, and 3 in pic) but the float breaks with variable lines of text. the developer outlines show that because box 1 is larger that box 2, box 3 doesn't float flush left like box 1 which screws up the flow. how do i keep the vertical height of box 1 and box 2 but make box 3 float left where it should be? Doing a float: right; does the same thing but just pushes 3 to the left is div 2 is larger than div 1
This is just an example, there could be a variable number of rows and columns so just doing an Nth div css rule won't work. (the containing div is a variable width based on a few conditions including responsive design)
Almost like i have to have a variable buffer at the bottom of each item in a row to match the height of the tallest one. I also don't want to use a min-height as on rows where the divs are the same height will result in extra white space where there shouldn't be. How would i get the tallest element in a row if the number of columns are variable?
A possible solution is to use the empty clearing div trick but again how do I get the number of divs in a row when columns are variable? I tried to force a nth child::after thing in the example but it didn't work
.item:nth-child(2)::after {
clear: both;
}
Search didn't show anything that works so if anyone has a post that does please let me know.
also have to stick with CSS2 if at all possible due to a bunch of users using older browsers that don't use CSS3

One solution is to use display:inline-block for the figures rather than float:left.
.figure {
display: inline-block;
vertical-align: top;
margin: 2px 1em;
border:1px solid grey;
}
.figcaption {
margin:1em;
}
<div class="section">
<div class="figure">
<img src="http://placehold.it/250x250" alt="#">
<div class="figcaption">
Line 1<br/>Line 2
</div>
</div>
<div class="figure">
<img src="http://placehold.it/250x250" alt="#">
<div class="figcaption">
Line 1
</div>
</div>
<div class="figure">
<img src="http://placehold.it/250x250" alt="#">
<div class="figcaption">
Line 1<br/>Line 2
</div>
</div>
</div>

You need to clear:both the 3rd element actually in this case.
See solution below.
img {
width:50%;
float:left;
}
img:nth-child(3) {
clear: both;
}
<img src="http://via.placeholder.com/350x160">
<img src="http://via.placeholder.com/350x150">
<img src="http://via.placeholder.com/350x150">
If you got some complex example please provide jsfiddle.

that's because your <div>s are styled with "float" and 3rd div has floated to 1st, because 1st is taller than others.
Possible solutions (not including the hardcoding - it's like a deadly sin):
Give equal height to each item in a set
.float {
background-color: #f90;
float: left;
height: 100px;
line-height: 100px;
margin: 10px;
text-align: center;
width: calc(50% - 20px);
}
<div class="float">float 1</div>
<div class="float">float 2</div>
<div class="float">float 3</div>
Use different approach, such as flexbox
.wrapper {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.flex {
background-color: #f90;
height: 100px;
line-height: 100px;
margin: 10px;
text-align: center;
width: calc(50% - 20px);
}
<div class="wrapper">
<div class="flex" style="height: 120px;">flex 1</div>
<div class="flex">flex 2</div>
<div class="flex">flex 3</div>
</div>

Related

div Margins with display: inline-block [duplicate]

This question already has answers here:
Better way to set distance between flexbox items
(40 answers)
Closed 9 months ago.
I'm trying to manipulate divs without using float, using display: inline-block; in my css allows me to get the siblings next to each other within a container div, but with inline-block, I can't space them apart using margin-left: 20px;, margin-right :20px; ... and so on.
I'm sure there's a really simple solution, even if it doesn't involve using display: inline-block;, I just want to avoid floats and preferably avoid padding too.
you can try flex-box method to create space between two div which is inside a div (I conclude that from your question )
.parent{
border:2px solid red;
display:flex;
justify-content:space-around;
}
.parent div{
border:3px solid black;
}
<div class="parent">
<div class="child1">
child1
</div>
<div class="child2">
child2
</div>
</div>
you can also add many child div as you want , they will automatically make place in the parent container.
Here you can see below how i managed to do so without display:inline-block; and this will not break on any device unlike inline-block.
.box {
width: 200px;
height: 200px;
background: #F3F3F3;
color: #000;
display: flex;
align-items: center;
justify-content: center;
margin-left: 20px;
}
.container {
display: flex;
margin-bottom: 40px;
}
.container.two {
justify-content: space-between;
}
.container.three {
justify-content: space-evenly;
}
Margin 20px in between
<div class="container">
<div class="box">
BOX 1
</div>
<div class="box">
BOX 1
</div>
</div>
Align boxes on left and right according to width
<div class="container two">
<div class="box">
BOX 1
</div>
<div class="box">
BOX 1
</div>
</div>
Align even spacing on left and right
<div class="container three">
<div class="box">
BOX 1
</div>
<div class="box">
BOX 1
</div>
</div>

Flexbox space-between except for rows with single items?

I have two divs. One needs to sit at the left, one at the right. A parent flexbox with justify-content: space-between works perfectly for this, except when the flex items wrap (which they should be able to do). After they wrap, they are left-aligned because there's only two items total.
How can I make rows with single items centre-aligned?
<div style="display: flex; justify-content: space-between; flex-wrap: wrap">
<div style="background: orange">
<strong>Canvas Prints</strong><br>
<span style="font-size: 14px; color: #ff0000">Create a masterpiece for any wall in your home!</span>
</div>
<div style="background: pink">
<img width="176" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTEAPU9xK-mE81DSwYqh_uMb_EUuqXT1yWzIvs9j7diGY-FHh6X">
</div>
</div>
(Or you can use the fiddle, because it's easier to squish the output pane of the fiddle than resize the whole SO window to see the divs wrap: https://jsfiddle.net/xv6oa418/1/)
Additional note: #KaranTewari suggested adding flex: 1 to the first child div, but I'd like text in the left div to not wrap until absolutely necessary (specifically, it should start wrapping only after the second flex item has wrapped onto the next line). The second div is actually going to be an image so I've updated my fiddle and snippet to reflect this.
I figured it out myself. I used flex-grow: 1 on the first/left div, and margin: auto on the second/right div. This makes the first div expand to take up all space so the auto margin of the second div doesn't get to do anything. Then when it wraps, the second div is no longer blocked by the first one and the auto margin takes over, centring the second div.
Like so:
<div style="display: flex; justify-content: space-between; flex-wrap: wrap">
<div style="background: orange; flex-grow: 1;">
<strong>Canvas Prints</strong><br>
<span style="font-size: 14px; color: #ff0000">Create a masterpiece for any wall in your home!</span>
</div>
<div style="background: pink; margin: auto">
<img width="176" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTEAPU9xK-mE81DSwYqh_uMb_EUuqXT1yWzIvs9j7diGY-FHh6X">
</div>
</div>
(And the fiddle: https://jsfiddle.net/xv6oa418/2/)
.parent {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.text {
background: orange;
padding:10px;
border-radius:10px;
}
.text:only-child {
background-color: green;
margin:0 auto;
}
<div class="parent">
<div class="text">
<strong>Canvas Prints</strong><br>
<span >Create a masterpiece for any wall in your home!</span>
</div>
<div class="img" >
<img width="176" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTEAPU9xK-mE81DSwYqh_uMb_EUuqXT1yWzIvs9j7diGY-FHh6X">
</div>
</div>
You can use :only-child selector and give margin:auto to the only-child element. Please see the snippet.
Try using
flex:1
This ensures you are using full available space, here jsfiddle edited
https://jsfiddle.net/karantewari/tfg0kymb/1/

change proportions of 3 columned display: table / table-cell

I have this simple setup:
.container {
display: table;
width: 70%;
text-align: center;
}
div {
border: 1px solid #336;
}
.column {
display: table-cell;
}
<div class="container">
<div class="column">Column 1.</div>
<div class="column">Column 2 is a bit longer.</div>
<div class="column">Column 3.</div>
</div>
jsFiddle: http://jsfiddle.net/aqk1yy1d/
This table-cell behavior expands with window resize. I would like the center cell/div to be fixed to its content and not expand. Basically the sides should expand but not the inner cell, wich should be the size of its content.
I don't see how I can do this without setting a defined width somewhere, but that in not ok, because I will have different length of content in that middle cell....
Any pointers?
The trick is to set both the left and right column to take up 50% of the width of the table. The center column gets a width of 1px. If there is content larger than 1px in the center column it will force the center column to grow.
The first example only has text inside it, which will wrap at the first moment. To mitigate this add something like white-space: nowrap to keep all text on a single line or make sure that you have content with a width.
.container {
display: table;
width: 70%;
text-align: center;
margin-bottom: 10px;
}
div {
border: 1px solid #336;
}
.column {
display: table-cell;
}
.left,
.right {
width: 50%;
}
.center {
width: 1px;
}
.center-content {
white-space: nowrap;
}
<div class="container">
<div class="column left">Column 1.</div>
<div class="column center">Column 2 is a bit longer.</div>
<div class="column right">Column 3.</div>
</div>
<div class="container">
<div class="column left">Column 1.</div>
<div class="column center"><div class="center-content">Column 2 is a bit longer.</div></div>
<div class="column right">Column 3.</div>
</div>
If you can't find a better solution, you could try using javascript to set the width dynamically. Change your html to something like this:
<div class="container">
<div class="column">Column 1.</div>
<div id="column2Outer" class="column">
<div id="column2Inner" style="display: inline-block">Column 2 is a bit longer.</div>
</div>
<div class="column">Column 3.</div>
</div>
The javascript would be as follows:
$("#column2Outer").css("width", document.getElementById("column2Inner").clientWidth);
You would call this on $(document).ready() or whenever the content changes. You would of course also have to remove the border from the inner column so you can't tell it's a nested div

html layout: how to float divs vertically

How do I get divs to float vertically like in this picture:
Background: I have a grid of checkboxes with content sorted alphabetically and I'd like to have alphabetic order progress vertically (since horizontal order is quite hard to follow). All the divs have same size (width like picture, height = 1 line size).
Update: To clarify: The main intention is to have a table layout with a variable amount of columns based on available screen width and have the cells in column-major order. The actual number of divs is not known in advance.
CSS
.cols {
width:20%;
float:left;
}
.rows {
height:100px;
}
HTML
<div class="cols">
<div class="rows">Div 1</div>
<div class="rows">Div 2</div>
<div class="rows">Div 3</div>
</div>
<div class="cols">
<div class="rows">Div 4</div>
<div class="rows">Div 5</div>
<div class="rows">Div 6</div>
</div>
<div class="cols">
<div class="rows">Div 7</div>
</div>
If you are willing to set a fix height on the table holding the cells you could use flexbox.
Set your holding container to:
display: flex;
flex-direction: column;
flex-wrap: wrap;
And your child elements to:
flex-grow: 20%;
min-width: 200px;
See the pen: http://codepen.io/anon/pen/qIpAl
#KunJ : compatibility of grid layout is very bad... ie10 + only,
http://caniuse.com/css-grid
I think without JS you can't do the tricks, I had the same problem, in order to resolve them, I've load all elements, count them et replace in the good div
Although the following is not a complete solution, maybe others can build on it to achieve the necessary result:
FIDDLE
Markup
Divs wrapped in a container div
CSS
div
{
width: 100px;
height: 50px;
background: orange;
border: 1px solid yellow;
display:block;
}
div:nth-child(4n)
{
display:table-cell;
}
.container
{
display:table;
width: 100%;
}

Set div to have its siblings width

I'm looking for a CSS solution to the following:-
<div style="display:inline;">
<div>The content of this div is dynamically created but will always be wider than
the below div.
</div>
<div> Need this div to have the same width as the above div.
</div>
</div>
The wrapper div has an inline display and works as expected, both child divs have dynamically generated content. I need the bottom one to take the width of the previous sibling.
Many thanks for any suggestions in advance.
Here's another Flexbox solution which allows for the second child to wrap to match the width of the variable height sibling.
.wrapper > div {
border: 1px solid;
}
.child {
display: flex;
}
.child div {
flex-grow: 1;
width: 0;
}
.wrapper {
display: inline-block;
}
<div class="wrapper">
<div>This div is dynamically sized based on its content</div>
<div class="child"><div>This div will always be the same width as the preceding div, even if its content is longer (or shorter too).</div></div>
</div>
Edit:
To support multiple divs under .child, where each div is on its own line, add break-after: always; ...
.child div {
flex-grow: 1;
width: 0;
break-after: always;
}
Floats and tables are so 2000 and late. With today's browsers we can make the two sibling DIVs match each other's width, regardless which is bigger/smaller.
Here's a Flexbox solution fit for 2016:
.wrapper {
display: inline-block;
}
.parent {
display: flex;
flex-direction: column;
}
/* For visualization */
.child {
border: 1px solid #0EA2E8;
margin: 2px;
padding: 1px 5px;
}
<div class="wrapper">
<div class="parent">
<div class="child">Child number one</div>
<div class="child">Child #2</div>
</div>
</div>
Set your div to display:inline-block instead, this way your div will expand with the content inside of it.
http://jsfiddle.net/CpKDX/
2023 keep it simple...
Use grid and the fr unit. Then you can split up into as many equally sized rows or columns as you want:
.container {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column-gap: 1em;
}
.container > div {
border: 1px solid black;
padding: 0.5em;
}
<div class="container">
<div>I'm a part of a grid. I will be split up into equal parts with my other sibling(s) depending on how many columns the grid is given.</div>
<div>I am a sibling element.</div>
</div>
Here is still a flexbox-based approach.
The essential idea: in an outermost wrapper, elements that need to be of equal width are wrapped into another wrapper.
.wrapper {
display: inline-block;
}
.flex-wrapper {
display: flex;
flex-direction: column;
}
.demo-bar {
height: 4px;
background-color: deepskyblue;
}
<div class="wrapper">
<div class="flex-wrapper">
<div contenteditable>Some editable text.</div>
<div class="demo-bar"></div>
</div>
</div>
Another practical example: an adaptive progress bar with the same width below a media (video or audio) element.
video.addEventListener("timeupdate", () =>
progress.style.width = `${video.currentTime / video.duration * 100}%`
)
.wrapper {
display: flex;
flex-direction: column;
position: relative;
align-items: center;
}
video {
display: block;
max-width: 100%;
}
.progress-bar {
height: 0.25rem;
background: #555;
}
#progress {
width: 0%;
height: 100%;
background-color: #595;
}
<div class="wrapper">
<div data-css-role="wrapper">
<video id="video" controls>
<source src="https://raw.githubusercontent.com/mdn/interactive-examples/master/live-examples/media/cc0-videos/flower.webm">
</video>
<div class="progress-bar">
<div id="progress"></div>
</div>
</div>
</div>
UPDATE: This works with me, I've just tried it:
<div style="max-width:980px;border:1px solid red;">
<div style="background:#EEE;float:left;">
<div style="width:auto;border:1px solid blue;float:left;">If you use 100% here, it will fit to the width of the mother div automatically.</div>
<div style="border:1px solid green;"> The div will be 100% of the mother div too.</div>
</div>
<div style="clear:both;"></div>
</div>
Is this what you want? The borders and background are just to show the divs ;)
Just go like this:
Let's say you want the whole divs be max. 980px (otherwise just leave that out or replace with 100%)...
<div style="max-width:980px;">
<div style="width:100%;">If you use 100% here, it will fit to the width of the mother div automatically.
</div>
<div style="width:100%;"> The div will be 100% of the mother div too.
</div>
</div>
The second option would be, to use one more div... or you use style="width:auto;" for the dynamic div...
Not sure if I understood what you are trying to do, but looks like setting a 100% width to the last div should work:
<div style="width:100%;">
BTW the style in the first div is not well defined, you should use a colon instead of a equal sign in the properties definition:
<div style="display:inline;">
If your willing to give up on a couple of <div>s then I have the solution for you:
<div style=“display: inline-block;”>
<table>
<tr>
<td>The table automatically makes its siblings the same width</td>
</tr>
<tr>
<td>So this will be as wide</td>
</tr>
</table>
</div>
Remember to set the div display:inline-block;