Positioning two variable-width inline-blocks relatively to each other - html

I have two variable-width elements that I'm trying to position the following way:
If they fit next to each other on the screen or in their common container, I want them align to the opposite sides of it (i.e. the second one aligned to right).
If they don't, I want them one above the other, but both aligned to the left.
Something as simple as:
<div class="container">
<div style="display: inline-block;">
I'm a variable width left element
</div>
<div style="display: inline-block; float:right;">
I'm right-floating if there's space
</div>
</div>
takes care of the first case, but obviously when the container is small enough for the second div to be rendered below the first one, it's still right-floating which is not what I want.
Is this even possible with pure CSS? I can't use media queries because of unknown/variable widths.

This layout and behavior is possible without media queries and pure CSS using flexbox.
HTML
<!-- horizontal alignment when two boxes fit -->
<div class="container">
<div class="box box1"><span>1</span></div>
<div class="box box2"><span>2</span></div>
</div>
<!-- vertical alignment when two boxes don't fit -->
<div class="container">
<div class="box box3"><span>1</span></div>
<div class="box box4"><span>2</span></div>
</div>
CSS
.container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
width: 700px; /* for demo only; can be relative length, as well */
}
.box1 { width: 100px; }
.box2 { width: 150px; }
.box3 { width: 400px; }
.box4 { width: 500px; }
DEMO
NOTES:
When there is enough space to fit both variable-width elements on the same row, they are aligned at opposite ends of the container with justify-content: space-between.
When there is not enough space to fit both elements, they wrap with flex-wrap: wrap and align-left because the justify-content: space-between rule will left-align an element when it is alone on the row.
Note that 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, post your CSS in the left panel here: Autoprefixer.

Related

How to align the children of two flex divs? [duplicate]

This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 2 years ago.
I'm creating a nav menu using flex. I want all of the items in my menu to display in a single row when the screen is wide enough to support that, and to snap to two rows of items when it needs to wrap. I have this mostly working:
.content {
width: 400px;
height: 150px;
border: thin solid black;
}
.outer {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.inner {
display: flex;
justify-content: space-around;
flex-grow: 1;
}
span {
font-size: 24pt;
}
<div class="content">
<div class="outer">
<div class="inner">
<span>one</span>
<span>two</span>
<span>three</span>
</div>
<div class="inner">
<span>four</span>
<span>five</span>
<span>six</span>
</div>
</div>
</div>
CodePen here.
This works perfectly when the page is wide enough:
And it works mostly perfectly when the page is narrow (try changing the width of .content to 250px):
However, now I'm trying to make it so the items in each row line up with each other. I'm going for something like this:
I've tried every combination of flex-grow, flex-shrink, and justify-content that I can think of, but I can't get the items to align.
I know I could probably use a media query and swap out the content for a grid when the window gets too narrow, but I'd like to simplify this as much as possible. Is there a way to align the children of two flex divs?
Alternatively, is there a way to use a grid layout that shows as 1 row until it needs to wrap, and then it shows as 2 rows?
It causes by span width.
if span width not fixed, span will have dynamic width;
set width on span;
Try this
Add to te span
span {
flex: 33%;
}
Or change the porcent acording to the amount of items the div has

Zurb Foundation 6 XY Grid using Grid Container within Flex-Container

I am using ZURB foundation 6 with XY grid and have run into a little problem and most likely something I'm doing wrong.
I want to center elements vertically so I use
<div class="flex-container">
<div class="grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>
And using jQuery I set the height of flex-container by using windowHeight = $(window).innerHeight();
Voila the items are vertically aligned... However two issues arise from this:
small-6 cell has a width of 50% that is not being respected and shrinks down to the approx length of the text.
flex-container unlike grid-container does not have a width or padding.
To resolve the issue I added some CSS like so:
.flex-container .align-middle {
max-width: 62.5rem;
margin: 0 auto;
width: 100%;
}
So while I've patched the issue I can't help thinking that there must be an easier way, a proper way using just classes. It seems odd that grid-container is setup to do so but flex-container is not.
The main problem here is that with flex-container, the grid-x element will, along being a flex container of its own, also become a flex row item, having the default flex item value 0 1 auto.
This means the grid-x won't grow wider than its content, hence width: 50% won't work on its children (small-6), as their parent doesn't have a width set.
By adding e.g. flex-child-grow or cell to the grid-x element, it will fill its parent's width, and the inner flex items will start behave as expected.
Note 1: With grid-container this is not needed since it is not a flex container, where the grid-x is a normal div, displayed as flex, which, like a block element, by default take full width of its parent.
Note 2: Both flex-container and grid-container does have a default width of 100%, it is the grid-x, when being a flex item, that cause the issue not taking its parent's width by default.
Stack snippet
/* for demo purpose */
body { margin: 0; }
.flex-container { height: 100vh; }
.grid-x { border: 1px solid red; }
.small-6 { border: 1px solid blue; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.css" rel="stylesheet"/>
<div class="flex-container">
<div class="flex-child-grow grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>

How to create a 3 column layout in css?

I have been trying to make a complex UI for my program and I wanted to be able to have 3 columns using css in my design.
This is currently my code:
<div style="width:100px;">stuff</div>
<div style="width:100px;">stuff</div>
<div style="width:100px;">stuff</div>
But this, for some reason, will display 3 different lines of stuff.
I have tried to change some things but it didn't seem to work at all
I just want there to be 3 columns on the same block.
If you want to have 3 differnet areas on the screen, the effective method for doing that would be:
<style> .third { width: 33.33%; float: left; } </style>
<div class="third"> Something </div>
<div class="third"> Something </div>
<div class="third"> Something </div>
The class="third" is adding the css that is inside of the {}'s that I have made. - Meaning that each of the div's are given the width: 33.33% (1/3 of the screen) and a float: left which will just move the areas to be able to move out of the normal CSS and HTML scope of stacking on top of each other.
Hope this helps! :)
There are a couple ways to accomplish what you want.
Method 1: Float and width
Assign a single column class
.column {
width: 33.3%;
float: left;
}
Markup three divs with said class
<div class="column">Column 1</div>
<div class="column">Column 2</div>
<div class="column">Column 3</div>
Method 2: Inline block
Sometimes floats aren't the best option. You cna also set the display property to inline-block, although this can sometimes leave unwanted gaps in between the divs.
.column {
width: 33.3%;
display: inline-block;
}
Same HTML markup
<div class="column">Column 1</div>
<div class="column">Column 2</div>
<div class="column">Column 3</div>
Method 3: Flexbox
Flexbox according to Chris Coyier of CSS-tricks:
The Flexbox Layout (Flexible Box) module (currently a W3C Last Call Working Draft) aims at providing a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word "flex").
.row {
display: -ms-flex: // Vendor prefixes required for flexbox
display: -webkit-flex;
display: flex:
}
.column {
width: 100px;
display: -ms-inline-flex;
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}
Add the parent div to your HTML markup
<div class="row">
<div class="column">Column 1</div>
<div class="column">Column 2</div>
<div class="column">Column 3</div>
</div>
Cool thing about flexbox is you don't need to fill the space using set percentages, it can space your columns out with justify-content: space-between;
There is a lot more to delve into with flexbox. Floats are very simple but since you mentioned building a UI, something like flexbox will give you a wider array of tools to work with.
Alternatively, you could style them all at once without giving a class as mentioned by Jek. If you are using styling within the html, you could do this in the header:
<style>
div{
width:100px
}
</style>
You could do the same if you are using an external stylesheet. However, if you have to style the divs in different manners using class and id would be a better option. If all divs are styled in the same way, simply style the tag, which is div in your case.

How to make a div float to a center of a container, along dynamic elements that will be added according to user's input

I'm trying to make a div float to the center of it's container div, but the thing is that the user may decide to add from 1 up to 12 elements, so they must float in lines of 4. So, if the user adds only one element, this should float to the center of the container, if he/she adds two, they must float to the center of the container but next to each other. If the User adds 5 elements, the first four must float side by side (filling the width 100% of the container) and the fifth should be on the second line, at the center. This images show what I want to achieve:
Image 1: One element
User input: only one box that floats to center.
Image 2: two elements
The user selected two elements, so both of them float side of each other and to the center of the container div.
Image 3: four elements
The user selected four elements, so the first side is full, the 100% of the container div is filled by four boxes of 25% with each.
Image 4: five elements
If the user selects 5 elements, the fifth one shall float to the center of the container div, right below the first line of the other 4 boxes.
With 6 boxes:
Seven boxes!
So, at the end, I'll be adding some asp.net vb that will bring the desired boxes to a repeater control, according to some data stored in a SQL database, and bringing the desired controls through a stored procedure.
I've been trying different techniques, but none of them have solved my issue (margin: 0 auto; display: inline-block; etc...)
Any help will be highly appreciated!!
Thanks
Here's a flexbox solution:
HTML
<div class="container">
<div class="box box1"><span>1</span></div>
<div class="box box2"><span>2</span></div>
<div class="box box3"><span>3</span></div>
<div class="box box4"><span>4</span></div>
<div class="box box5"><span>5</span></div>
<div class="box box6"><span>6</span></div>
<div class="box box7"><span>7</span></div>
<div class="box box8"><span>8</span></div>
<div class="box box9"><span>9</span></div>
<div class="box box10"><span>10</span></div>
<div class="box box11"><span>11</span></div>
<div class="box box12"><span>12</span></div>
</div>
CSS
html { height: 100%; }
body {
height: 100%;
background-color: yellow;
}
.container {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
flex-wrap: wrap;
width: 400px;
height: 100%;
margin: auto;
}
.box {
height: 50px;
width: 75px;
margin: 10px;
background-color: lightgreen;
border: 1px solid #aaa;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
}
DEMO
In the demo, try removing any number of divs. Remaining divs will always be centered.
Note that 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, post your CSS in the left panel here: Autoprefixer.

Grid positioning with flexbox [duplicate]

I try to use the following structure to generate the layout described below.
<div class="flexbox">
<div class="box box1">child 1</div>
<div class="box box2">child 2</div>
<div class="box box3">child 3</div>
<div class="box box4">child 4</div>
</div>
I made an example for that here.
The layout should be as follows:
if there is only one box inside the flexbox it should have 50% of the width inside the flexbox (see following figure)
if there are two boxes they both should take 50% of the space inside the flexbox
if there are three boxes, each box should take 50% of the space, while the first two boxes are in row 1 and the third box appears in row 2
How can I achieve this kind of layout with css?
Edit: The boxes might not have the same height. This means they should fill the remaining space vertically. The width is always the same. See the following image for an example.
Edit: I found a way to make masonry with pure css see here: http://jsfiddle.net/confile/aGXzU/
The problem is that the boxes are in the wrong order. They should be from left to right and from top to bottom like this:
1 2 3
4 5 6
7 8 9
Is there a way to get this with css and only little javascript?
Here is a new answer and hope it solves your problem , following two Fiddles , to handle this issue , the first script will throw all odd children in the left side , and all even children on the right side
side1=0,side2=0
$(".flexbox").children().each(function(index, element) {
if (index % 2 === 0) //odd children (starts with 0 )
{
$(this).css("top",side1+"px")
side1+=parseInt($(this).css("height"))
}
else //even children
{
$(this).css("top",side2+"px")
$(this).css("left","50%")
side2+=parseInt($(this).css("height"))
}
});
http://jsfiddle.net/prollygeek/QD9kZ/
while this second fiddle , will balance the two sides based on elements heights so that there is no big deviation in the columns heights all the time , use any script of them it is up to you.
side1=0,side2=0
$(".flexbox").children().each(function(index, element) {
if(side1<=side2)
{
$(this).css("top",side1+"px")
side1+=parseInt($(this).css("height"))
}
else if(side2<side1)
{
$(this).css("top",side2+"px")
$(this).css("left","50%")
side2+=parseInt($(this).css("height"))
}
});
http://jsfiddle.net/prollygeek/hP6fS/
Flexbox cannot be used to recreate the Masonry layout. Period.
Flexbox is for controlling how elements flow along either a horizontal row (flex-direction: row, which is the default) or vertical column (flex-direction: column). That means you can only eliminate excess space in one direction: left/right (row) or top/bottom (column). Because flex-direction: column requires an explicit height to enable wrapping, it is entirely unsuitable for this purpose.
The CSS Multi-column Layout Module is the closest you can get to recreating a Masonry layout using pure CSS, but it still only allows you to eliminate excess space between the elements in one direction: vertically. The key difference between this and Flexbox (using the column direction) is that the Multi-Column module does not require an explicit height and will distribute the contents equally between each of the columns as best it can (this can be controlled via the column-fill property). The gap between the columns is controlled by the column-gap property.
http://codepen.io/cimmanon/pen/CcGlE
.my-element {
-moz-columns: 15em;
-webkit-columns: 15em;
columns: 15em;
}
If there are only two columns, why not just use floats, alternating left and right floating/clearing for odd and even boxes?
.container {
background-color: yellow;
overflow: hidden;
width: 100%;
}
.box {
height: 100px;
width: 50%;
}
.box:nth-child(odd) {
float:left;
clear: left;
}
.box:nth-child(even) {
float:right;
clear: right;
}
.box1 {
background-color: lime;
}
.box2 {
background-color: blue;
height: 120px;
}
.box3 {
background-color: red;
height: 140px;
}
.box4 {
background-color: green;
}
<div class="container">
<div class="box box1">child 1</div>
<div class="box box2">child 2</div>
<div class="box box3">child 3</div>
<div class="box box4">child 4</div>
</div>
.flexbox {
background-color: yellow;
width: 100%;
height: 300px;
}
.box {
float:left;
position:realtive;
height: 100px;
width:50%;
}
try adding and removing children !!
http://jsfiddle.net/prollygeek/8hHDg/5/
For boxes of the same size:
If you're using flexbox, you'll want to use flex-direction: row; and flex-wrap: wrap;
I forked your JSFiddle. All flex-box properties I added are prefixed with -webkit- only
References:
A Complete Guide to Flexbox
How do I implement a multi-line flexbox?
For boxes of multiple sizes:
You'll need a 'masonry' layout. This article should help you with this issue. The last section is entitled 'Pure CSS'; if you want to avoid JavaScript plugins, that should be what you want.
Unfortunately, pure CSS is only able to make top-to-bottom left-to-right layouts. For left-to-right top-to-bottom layouts, you'll need JavaScript. Check out the jQuery suggestions in the article above.
If you want to do this with pure JavaScript (without jQuery), check out this masonry library.