Left aligning absolutely positioned div while maintaining fluidity - html

I have the following HTML structure:
<div id="outer">
<div id="left">
<div id="leftContainer"><span>bla</span><span>bla</span><span>bla</span><span>bla</span></div>
</div>
<div id="right">
<div class="item"><span>item text 1</span></div>
<div class="item"><span>item text 2</span></div>
<div class="item"><span>item text 3</span></div>
<div class="item"><span>item text 4</span></div>
<div class="item"><span>item text 5</span></div>
<div class="item"><span>item text 6</span></div>
</div>
</div>
With the corresponding styles:
#left, #right {
display: inline-block;
}
.item {
display:inline-block;
padding: 0px 5px;
}
#right {
position: absolute;
/*right:0px;*/ /*this little thing causes my problems*/
text-align:right;
border-color: red;
}
I need the right div to be right aligned. For that I set right:0px; but then the right element overlap the left div. If right:0px; is not set, then the item elements will break on a new line (which is part of my requirements) but the right element will be, obviously, left aligned. See the fiddle, comment/uncomment right:0px; and play with the width of the result panel.
Is the a way of right aligning the right div without overlapping? Floating is currently not a solution.

I'm not entirely clear on how the right div is supposed to behave after the 'collision' point but flexbox does allow for the alignment you wanted without the overlap that seems to be problematical for you.
#outer {
position: relative;
display: flex;
justify-content: space-between;
}
#outer {
position: relative;
display: flex;
justify-content: space-between;
}
div {
border: 1px solid black;
}
#left div span {
margin: 0px 5px;
display: inline-block;
}
.item {
display: inline-block;
padding: 0px 5px;
}
#right {
text-align: right;
border-color: red;
}
<div id="outer">
<div id="left">
<div id="leftContainer">
<span>bla</span>
<span>bla</span>
<span>bla</span>
<span>bla</span>
</div>
</div>
<div id="right">
<div class="item"><span>item text 1</span>
</div>
<div class="item"><span>item text 2</span>
</div>
<div class="item"><span>item text 3</span>
</div>
<div class="item"><span>item text 4</span>
</div>
<div class="item"><span>item text 5</span>
</div>
<div class="item"><span>item text 6</span>
</div>
</div>
</div>
JSFiddle Demo

As i understand you need something like following.
Use display:table-cell will solve your issue:
#left, #right {
display: table-cell;
}
Check Fiddle Here.
Give width: 100%; to .right wills stick right div to right align.
Check Updated Fiddle Here.

Use the flexbox model display: flex for your #right element.
#outer {
overflow: hidden;
}
#left {
float: left;
min-width: 66%;
background-color: #69f;
}
#right {
min-width: 34%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-end;
align-items: stretch;
}
.item {
display: inline-block;
}
See example here: http://jsbin.com/qalilu/3/edit. I've added a min-width constraint, which may be useful.
See browser support: http://caniuse.com/#search=flexbox
And a guide: https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Related

center div cutting into floated left div

I'm trying to align three divs horizontally.
The center div is cutting into the left div.
What am I doing wrong?
<div>
<div style={{width:"100px", border:"solid blue", float:"left"}}>Left some text some text some text</div>
<div style={{width:"100px", border:"solid green", float:"right"}}>Right</div>
<div style={{border:"solid red", margin:"0 auto"}}>Center</div>
<div style={{clear:"both"}}></div>
</div>
The center overlaps the right green box as well but the border sizes are the same so you can't see it.
Give the red div margin-left:100px:
<div>
<div style="width:100px;border:1px solid blue;float:left">Left some text some text some text</div>
<div style="width:100px;border:1px solid green;float:right">Right</div>
<div style="border:1px solid red;margin-left:100px">Center</div>
<div style="clear:both"></div>
</div>
Maybe You should use flexbox ? i think it's much more convenient and more modern than "float" conception. This my proposition.I hope You will be content ;-) If you want, you can switch from width to flex properties, they are commented in css.
.wrapper {
display: flex;
align-items: start;
justify-content: space-between;
width: 100%;
text-align: center;
}
.blue {
width: 100px;
/* flex: 1; */
border:1px solid blue;
}
.green {
width: 100px;
/* flex: 1; */
border:1px solid green;
}
.red {
width: 100%;
/* flex: 8; */
border:1px solid red;
margin: 0 auto;
}
<div class="wrapper">
<div class="blue">Left some text some text some text</div>
<div class="red">Center</div>
<div class="green">Right</div>
</div>

Is it possible to horizontally center align full width div list items inside other container div?

Picture describes it better, so I am attaching it.
So, this is simple list. Green areas are clickable and what I want to achieve is centering texts inside those green buttons, but those texts also should be aligned to left side. Not sure if I am being clear enough, but I do hope picture will explain the idea.
Tried to play with flex, but not successfully.
#container {
display: flex;
flex-direction: column;
align-items: center;
}
.item {
border: 1px solid red;
}
<div id="container">
<div id="otherContainer">
<div class="item">some text</div>
<div class="item">sone loooonger text</div>
<div class="item">text</div>
</div>
</div>
I expect to have some clean css which would allow me to have desired result as you can see in picture. So, question is, is it even possible to achieve without hackish css/JS solutions?
Yes, its possible to do this without javascript, but it comes with some limitations like having to set a max-width.
button {
display: block;
width: 100%;
border: none;
}
div {
margin: 1rem auto;
max-width: 100px;
text-align: left;
}
.bg-green {
background: green;
}
.bg-lightgreen {
background: lightgreen;
}
<button class="bg-green">
<div>Some text</div>
</button>
<button class="bg-lightgreen">
<div>Some other text</div>
</button>
<button class="bg-green">
<div>Text</div>
</button>
Here is a trick using table:
#container {
display: table;
width:100%;
}
.item {
background: yellow;
display:table-row;
white-space:nowrap;
}
.item:before,
.item:after{
content: "";
display:table-cell;
width:50%;
}
.item:hover {
background: red;
}
<div id="container">
<div class="item">some text</div>
<div class="item">sone loooonger text</div>
<div class="item">text</div>
</div>

How to use flex to align button with centered text but icon to one side? [duplicate]

I'm using flexbox to align my child elements. What I'd like to do is center one element and leave the other aligned to the very left. Normally I would just set the left element using margin-right: auto. The problem is that pushes the center element off center. Is this possible without using absolute positioning?
HTML & CSS
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: center;
margin: 0 auto;
width: 500px;
}
#left {
margin-right: auto;
}
#center {
margin: auto;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Add third empty element:
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
And the following style:
.parent {
display: flex;
}
.left, .right {
flex: 1;
}
Only left and right are set to grow and thanks to the facts that...
there are only two growing elements (doesn't matter if empty) and
that both get same widths (they'll evenly distribute the available space)
...center element will always be perfectly centered.
This is much better than accepted answer in my opinion because you do not have to copy left content to right and hide it to get same width for both sides, it just magically happens (flexbox is magical).
In action:
.parent {
display: flex;
}
.left,
.right {
flex: 1;
}
/* Styles for demonstration */
.parent {
padding: 5px;
border: 2px solid #000;
}
.left,
.right {
padding: 3px;
border: 2px solid red;
}
.center {
margin: 0 3px;
padding: 3px;
border: 2px solid blue;
}
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
EDIT: See Solo's answer below, it is the better solution.
The idea behind flexbox is to provide a framework for easily aligning elements with variable dimensions within a container. As such, it makes little sense to provide a layout where the width of one element is totally ignored. In essence, that is exactly what absolute positioning is for, as it takes the element out of the normal flow.
As far as I know, there is no nice way of doing this without using position: absolute;, so I would suggest using it... but If you REALLY don't want to, or can't use absolute positioning then I suppose you could use one of the following workarounds.
If you know the exact width of the "Left" div, then you could change justify-content to flex-start (left) and then align the "Center" div like this:
#center {
position: relative;
margin: auto;
left: -{half width of left div}px;
}
If you do not know the width, then you could duplicate "Left" on the right side, use justify-content: space-between;, and hide the new right element:
Just to be clear, this is really, really ugly... better to use absolute positioning than to duplicate content. :-)
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: space-between;
margin: 0 auto;
width: 500px;
}
#right {
opacity: 0;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Left</span>
</div>
.parent {
display: flex;
}
.left {
flex: 1;
}
.parent::after {
flex: 1;
content: '';
}
<div class="parent">
<div class="left">Left</div>
<div>Center</div>
</div>
I have another solution. In my opinion, Adding an empty block to the center element is fine but code-wise it bit ugly.
Since this is 4 years old I figured I'd update this with a much easier CSS Grid solution.
#parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 1px solid black;
margin: 0 auto;
width: 500px;
}
#center {
text-align: center;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
If you don't want to rely on positioning, the only way I've found that makes it truly centered is to use a combination of auto margin and negative margin prevent the centered element to getting pushed over by the left aligned element. This requires that you know the exact width of the left aligned element though.
.container {
height: 100px;
border: solid 10px skyblue;
display: flex;
justify-content: center;
}
.block {
width: 120px;
background: tomato;
}
.justify-start {
margin-right: auto;
}
.justify-center {
margin-right: auto;
margin-left: -120px;
}
<div class="container">
<div class="block justify-start"></div>
<div class="block justify-center"></div>
</div>
As far as I know this is possible with the following code.
https://jsfiddle.net/u5gonp0a/
.box {
display: flex;
justify-content: center;
background-color: green;
text-align: left;
}
.left {
padding: 10px;
background-color: pink;
}
.center {
padding: 10px;
background-color: yellow;
margin: 0 auto;
}
<div class="box">
<div class="left">left</div>
<div class="center">center</div>
</div>
Try this no hacks :)
CSS
.container{
width: 500px;
margin: 0 auto;
}
.box{
display: flex;
align-items: center;/* just in case*/
justify-content: space-between;
}
.box p:nth-child(2){
text-align: center;
background-color: lime;
flex: 1 1 0px;
}
HTML
<div class="container">
<div class="box">
<p>One</p>
<p>Two</p>
</div>
</div>
http://codepen.io/whisher/pen/XpGaEZ
If you have a grid system you can use it to do what you want without "extra" css.
Below with bootstrap (V 4.X)
Note: It uses flex under the hood
<div class="row">
<div class="col text-left">left</col>
<div class="col text-center">center</col>
<div class="col text-right">right</col>
</div>
Doc bootstrap: https://getbootstrap.com/docs/4.6/layout/grid/
Et voilĂ  ! :)
Solution 1: give 50% width to center element and use justify-content:space-between
#parent {
display: flex;
justify-content: space-between;
}
#center {
flex-basis: 50%;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Solution 2: Add one dummy element and hide it.
#parent {
display: flex;
justify-content: space-between;
}
#right {
visibility:hidden;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Right</span>
</div>

2 Inner divs - one should be center and not collide with the other [duplicate]

I'm using flexbox to align my child elements. What I'd like to do is center one element and leave the other aligned to the very left. Normally I would just set the left element using margin-right: auto. The problem is that pushes the center element off center. Is this possible without using absolute positioning?
HTML & CSS
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: center;
margin: 0 auto;
width: 500px;
}
#left {
margin-right: auto;
}
#center {
margin: auto;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Add third empty element:
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
And the following style:
.parent {
display: flex;
}
.left, .right {
flex: 1;
}
Only left and right are set to grow and thanks to the facts that...
there are only two growing elements (doesn't matter if empty) and
that both get same widths (they'll evenly distribute the available space)
...center element will always be perfectly centered.
This is much better than accepted answer in my opinion because you do not have to copy left content to right and hide it to get same width for both sides, it just magically happens (flexbox is magical).
In action:
.parent {
display: flex;
}
.left,
.right {
flex: 1;
}
/* Styles for demonstration */
.parent {
padding: 5px;
border: 2px solid #000;
}
.left,
.right {
padding: 3px;
border: 2px solid red;
}
.center {
margin: 0 3px;
padding: 3px;
border: 2px solid blue;
}
<div class="parent">
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right"></div>
</div>
EDIT: See Solo's answer below, it is the better solution.
The idea behind flexbox is to provide a framework for easily aligning elements with variable dimensions within a container. As such, it makes little sense to provide a layout where the width of one element is totally ignored. In essence, that is exactly what absolute positioning is for, as it takes the element out of the normal flow.
As far as I know, there is no nice way of doing this without using position: absolute;, so I would suggest using it... but If you REALLY don't want to, or can't use absolute positioning then I suppose you could use one of the following workarounds.
If you know the exact width of the "Left" div, then you could change justify-content to flex-start (left) and then align the "Center" div like this:
#center {
position: relative;
margin: auto;
left: -{half width of left div}px;
}
If you do not know the width, then you could duplicate "Left" on the right side, use justify-content: space-between;, and hide the new right element:
Just to be clear, this is really, really ugly... better to use absolute positioning than to duplicate content. :-)
#parent {
align-items: center;
border: 1px solid black;
display: flex;
justify-content: space-between;
margin: 0 auto;
width: 500px;
}
#right {
opacity: 0;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Left</span>
</div>
.parent {
display: flex;
}
.left {
flex: 1;
}
.parent::after {
flex: 1;
content: '';
}
<div class="parent">
<div class="left">Left</div>
<div>Center</div>
</div>
I have another solution. In my opinion, Adding an empty block to the center element is fine but code-wise it bit ugly.
Since this is 4 years old I figured I'd update this with a much easier CSS Grid solution.
#parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 1px solid black;
margin: 0 auto;
width: 500px;
}
#center {
text-align: center;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
If you don't want to rely on positioning, the only way I've found that makes it truly centered is to use a combination of auto margin and negative margin prevent the centered element to getting pushed over by the left aligned element. This requires that you know the exact width of the left aligned element though.
.container {
height: 100px;
border: solid 10px skyblue;
display: flex;
justify-content: center;
}
.block {
width: 120px;
background: tomato;
}
.justify-start {
margin-right: auto;
}
.justify-center {
margin-right: auto;
margin-left: -120px;
}
<div class="container">
<div class="block justify-start"></div>
<div class="block justify-center"></div>
</div>
As far as I know this is possible with the following code.
https://jsfiddle.net/u5gonp0a/
.box {
display: flex;
justify-content: center;
background-color: green;
text-align: left;
}
.left {
padding: 10px;
background-color: pink;
}
.center {
padding: 10px;
background-color: yellow;
margin: 0 auto;
}
<div class="box">
<div class="left">left</div>
<div class="center">center</div>
</div>
Try this no hacks :)
CSS
.container{
width: 500px;
margin: 0 auto;
}
.box{
display: flex;
align-items: center;/* just in case*/
justify-content: space-between;
}
.box p:nth-child(2){
text-align: center;
background-color: lime;
flex: 1 1 0px;
}
HTML
<div class="container">
<div class="box">
<p>One</p>
<p>Two</p>
</div>
</div>
http://codepen.io/whisher/pen/XpGaEZ
If you have a grid system you can use it to do what you want without "extra" css.
Below with bootstrap (V 4.X)
Note: It uses flex under the hood
<div class="row">
<div class="col text-left">left</col>
<div class="col text-center">center</col>
<div class="col text-right">right</col>
</div>
Doc bootstrap: https://getbootstrap.com/docs/4.6/layout/grid/
Et voilĂ  ! :)
Solution 1: give 50% width to center element and use justify-content:space-between
#parent {
display: flex;
justify-content: space-between;
}
#center {
flex-basis: 50%;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
</div>
Solution 2: Add one dummy element and hide it.
#parent {
display: flex;
justify-content: space-between;
}
#right {
visibility:hidden;
}
<div id="parent">
<span id="left">Left</span>
<span id="center">Center</span>
<span id="right">Right</span>
</div>

Align items baseline for a select

I've got a header. In this header there's a title and a picker. The picker is a simple label with a select underneath it. I wish to align the baselines of the title and the text inside the select. If I use align-items: baseline, then the baseline of the title is aligned with the baseline of the label, not the text in the select.
How can I align the baseline of the title with the baseline of the select, instead of the label?
The reproducing code is
<div style="display:flex;align-items:baseline">
<span style="font-size:23px;padding-top:16px">A title</span>
<div>
<div><span>A label</span></div>
<div><select><option>An option</option></select></div>
</div>
</div>
How can I align the baseline of the title with the baseline of the
select, instead of the label?
Based on your markup, what you need is margin-top:auto on your title span.
div.wrap > span { margin-top: auto; }
However, that may not really be an exact baseline because that would depend a lot on the font-size, line-height, padding etc. not only on your title span but also on the select itself.
The snippet below will help to visualize that with the red line showing the baselines:
Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
div.wrap { display: flex; margin: 8px; position: relative; }
div.wrap > span { margin-top: auto; margin-right: 4px; font-size: 1.5em; }
div.wrap select { padding: 2px; }
div.wrap::after {
content: ''; display: block;
position: absolute; left: -4px; bottom: 4px;
width: 240px; height: 1px;
background-color: #f00;
}
<div class='wrap'>
<span>A title</span>
<div>
<div><span>A label</span></div>
<div><select><option>An option</option></select></div>
</div>
</div>
Accompanying Fiddle: http://jsfiddle.net/abhitalks/n4z98wvn/
Now why is baseline not aligning with the baseline? It actually does. If you split your label into multiple lines, you'll see that it does align with the baseline of the first line. You could see that clearly by comparing it with flex-start.
As pointed out by #Paulie_D, you could also get the intended result with flex-end. However the same problem as mentioned in my first solution, remains. You could see that clearly by comparing it with a reduced line-height on title.
Below are all the comparisons.
Comparison Snippet:
* { box-sizing: border-box; padding: 0; margin: 0; }
div.wrap { display: flex; align-items: baseline; margin: 16px; }
div.wrap > span { font-size: 23px; border: 1px solid #ddd; }
div.wrap:nth-of-type(2) { align-items: flex-start; }
div.wrap:nth-of-type(3) { align-items: flex-end; }
div.wrap:nth-of-type(4) { align-items: flex-end; }
div.wrap:nth-of-type(4) > span { line-height: 20px; }
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines,
is aligned at baseline with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines,
is aligned at flex-start with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines.
The select is mis-aligned with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
<div class="wrap">
<span>A title</span>
<div>
<div>
<span>
A label<br/>which breaks into<br/>lines.
The select is aligned neatly with the title.
</span>
</div>
<div><select><option>An option</option></select></div>
</div>
</div>
Comparison Fiddle:http://jsfiddle.net/abhitalks/r8spzk54/1/
Try this:
HTML (no changes; except removed some inline styles and added id)
CSS
#container {
display: flex;
}
#container > div {
display: flex;
flex-direction: column;
}
DEMO: http://jsfiddle.net/c7n0222p/4