Dynamic width of table div - html

I need to have a div construct with a table-display, while the first cell should be as wide as the content fit to it without linebreak. The second cell should take the rest of the width,
html
<div class="table full-width">
<div class="table-cell">Cell 1 without br</div>
<div class="table-cell">Cell 2 just the rest width</div>
</div>
css
.full-width {
width: 100%;
}
.table {
display: table;
}
.table-cell {
display: table-cell;
}

I would highly recommend not explicitly styling <div>s as table elements. Use the default HTML elements for that, or perhaps use more fluid formatting styles, such as float.
However, I suggest you use the more modern CSS3 flex-box, with its children style flex-grow. It gives you a lot more flexibility in situations like these.
div.container {
display: flex;
background-color: lightgrey;
padding: 20px;
justify-content: space-between;
}
div.shrink, div.grow {
padding: 20px;
margin: 0 10px;
background-color: grey;
flex-basis: auto;
}
div.shrink {
flex-shrink: 1;
}
div.grow {
flex-grow: 1;
}
<div class="container">
<div class="shrink">
This will shrink!
</div>
<div class="grow">
This will grow!
</div>
</div>

You can try this:
HTML
<div class="table full-width">
<div class="table-cell">Cell 1 without br</div>
<div class="table-cell cell-wide">Cell 2 just the rest width</div>
</div>
CSS
.full-width {
width: 100%;
}
.table {
display: table;
}
.table-cell {
display: table-cell;
white-space: pre;
}
.cell-wide {
width: 100%
}
Fiddle

Related

Get rid of empty space on the right when word-wrap happens [duplicate]

This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
Closed 1 year ago.
Below is simple example illustrating the problem. I have "Stackoverflow Stackoverflow" string and in first case it is displayed as a single line and in the second case word wrap happens. As you can see in the second case width of the div element is wider than a single "Stackoverflow" word. Is there a way to get rid of this empty space on the right? Resulting element has width 200px as specified per max-width but I want element to have actual width which is enough to fit it into 200px after word wrap.
body {
font-size: 30px;
}
.row {
margin-bottom: 10px;
}
.text-no-wrap {
background: yellowgreen;
white-space: nowrap;
display: inline-block;
}
.text-wrap {
max-width: 200px;
background: tomato;
white-space: normal;
display: inline-block;
}
<div class="row">
<div class="text-no-wrap">Stackoverflow Stackoverflow</div>
</div>
<div class="row">
<div class="text-wrap">Stackoverflow Stackoverflow</div>
</div>
You could try adding width: max-content; to the div's insde the .row
Note that width: max-content; isn't supported in Internet Explorer, but is supported on all other browsers.
Check the support of width: max-content; here.
I've added flex-direction: column; to the .row so the children of those
div's will appear underneath each other.
If you need display: flex; on the .row div, then This is the way to go. If you don't need display: flex; on the .row div, just simply remove it. And only use width: max-content; on the children;
body {
font-size: 30px;
}
.row {
display: flex;
flex-direction: column;
margin-bottom: 10px;
}
.text-no-wrap {
width: max-content;
background: yellowgreen;
}
.text-wrap {
width: max-content;
background: tomato;
}
<div class="row">
<div class="text-no-wrap">Stackoverflow1 Stackoverflow2</div>
</div>
<div class="row">
<div class="text-wrap">Stackoverflow1 Stackoverflow2</div>
<div class="text-wrap">Stackoverflow1 Stackoverflow2</div>
</div>
I believe this one is not a text-wrap issue. If you check the following code you will get multiple spaces in between wrapping text. This one is due to the
max-width: 200px;
specified for
.text-wrap.
body {
font-size: 30px;
}
.row {
display: flex;
margin-bottom: 10px;
}
.text-no-wrap {
background: yellowgreen;
white-space: nowrap;
}
.text-wrap {
max-width: 200px;
background: tomato;
white-space: normal;
}
<html>
<body>
<div class="row">
<div class="text-no-wrap">Stackoverflow Stackoverflow</div>
</div>
<div class="row">
<div class="text-wrap">Stackoverflow Stackoverflow testing text wrapping space issue</div>
</div>
</body>
</html>
Go through the demo you can see that after "testing text" multiple spaces is there.

Changing the order of elements and wrap after specific element with flexbox

I'm trying to create this structure using only flexbox.
This is how my html looks like.
<div class="container">
<div class="first_container"></div>
<div class="second_container"></div>
<div class="third_container"></div>
</div>
I know it's really basic problem if i could just change divs order or add additional wrapper for the first line. The problem is it have to stay as it is.
Basic dimensions:
1. first_container - should takes 100% minus third_container width
2. second_container - shoudl takes 100%
I am asking for some tips, because my hands are slowly falling.
You can use flexbox order property
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
}
.container div {
padding: 10px;
border: 5px solid #fff;
background: gray;
text-align: center;
}
.first_container {
width: 70%;
order: 1;
}
.second_container {
width: 100%;
order: 3;
}
.third_container {
width: 30%;
order: 2;
}
<div class="container">
<div class="first_container">1</div>
<div class="second_container">2</div>
<div class="third_container">3</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>

Justify elements with fix space (variable width)

I have a container with a variable number of elements in it.
The elements should be justified but with a fix space between (e.g. 20px).
That means the width of every element has to adapt.
For example this:
HTML
<div class="container">
<div>
<img src="...">
</div>
<div>
<img src="...">
</div>
<div>
<img src="...">
</div>
</div>
CSS
div.container {
text-align: justify;
}
div.container div {
display: inline-block;
margin-right: 20px;
}
div.container div img {
width: 100%;
}
At the end it should look like this (this picture shows two examples: 2 elements and 3 elements; the width is dynamic but the space fix [20px]):
It should work with a different number of child elements.
Is there a professional way to do this with CSS?
EDIT: I should mention that this fix space is a %-value!
If using Flexbox is an option, you could add flex: 1 to the flex items and also a margin property with a fixed value as follows:
EXAMPLE HERE
div.container { display: flex; }
div.container div {
height: 50px; /* Just for demo */
flex: 1;
margin-left: 20px;
}
div.container :first-child { margin-left: 0; }
Actually, flex: 1 is a shorthand of flex-grow: 1; in this case.
You can use display: table and display: table-cell for this:
.container {
display: table;
width: 100%;
border-spacing: 10px 0;
border-collapse: separate;
background: palevioletred;
}
.container div {
display: table-cell;
}
.container img {
display: block;
width: 100%;
height: auto;
}
<div class="container">
<div><img src="//dummyimage.com/200x100/000/CCC"></div>
<div><img src="//dummyimage.com/300x100/000/CCC"></div>
<div><img src="//dummyimage.com/400x100/000/CCC"></div>
</div>
<hr/>
<div class="container">
<div><img src="//dummyimage.com/200x100/000/CCC"></div>
<div><img src="//dummyimage.com/400x100/000/CCC"></div>
</div>
<hr/>
<div class="container">
<div><img src="//dummyimage.com/600x100/000/CCC"></div>
</div>