In the following code, I'm trying to build table like design with flexbox display model.
.wrapper {
width: 500px;
height: 150px;
background: grey;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.row {
display: flex;
flex-direction: row;
flex: 1;
border: 3px solid green;
}
.cell {
flex: 1;
border: 1px solid red;
}
<div class="wrapper">
<div class="container">
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
</div>
<div class="row" style="overflow: auto;">
<div class="cell">1</div>
<div class="cell">
<div style="height: 200px;">huge content</div>
</div>
<div class="cell">3</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
</div>
</div>
</div>
My problem is, that in second row (with that "huge content") is scrollbar, and that scrollbar is taking space from my row cells and that's huge problem because my columns don't have the same width and it doesn't look like a table.
Things I can't use:
my own implementation of scrollbars (performance is an issue).
fixed widths of columns or .container (components height and width has to adapt).
Real world usage of component
So, I need to make the scrollbar in the second row to be above that content and not to take that space.
I found, that exists overflow: overlay , which works as I want.
It renders the scrollbar, but doesn't take that space
See: demo
I think you are looking for this..
JSFIDDLE
Code used -
::-webkit-scrollbar {
width: 10px;
height:10px;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.8);
border-radius: 6px;
background-color: grey;
}
::-webkit-scrollbar-thumb {
border-radius: 6px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.9);
background-color: grey;
}
Related
I want to display divs in 2 columns ordered from above to below:
I tried the following solution based on column-count which works nice if the number of divs is even but breaks if it's odd.
.container {
column-count:2;
}
.square {
box-sizing: border-box;
border: 1px solid black;
height: 200px;
padding: 5px;
}
<div class="container">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
</div>
Then I tried a solution based on flex, but I can't seem to find a solution for the order:
.container {
display:flex;
flex-wrap: wrap;
}
.square {
box-sizing: border-box;
border: 1px solid black;
flex: 0 0 50%;
height: 200px;
}
<div class="container">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
</div>
What I want to achieve is smoothing like this:
add display:inline-block;width:100%; to the square element:
.container {
column-count: 2;
}
.square {
border: 1px solid black;
height: 200px;
display:inline-block;
width:100%;
}
<div class="container">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
</div>
A very short prehistory
My story begins with struggling to make overflow-wrap: break-word; working inside a flexbox. Flexbox container didn't want to understand that its item can be shrunk despite the fact that the item can break long words:
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex-column {
display: flex;
}
.item {
overflow-wrap: break-word;
background-color: #fff;
padding: 8px;
}
<div class="body">
<div class="flex-column">
<div class="item">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
Fortunately, we can help flexbox to understand that it can shrink its item using min-width: 0; on the item:
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex-column {
display: flex;
}
.item {
overflow-wrap: break-word;
background-color: #fff;
padding: 8px;
/* Okay, it fixes this */
min-width: 0;
}
<div class="body">
<div class="flex-column">
<div class="item">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
However, the real world is a little bit more complicated.
The problem
In our application, we have many nested flexboxes. So the example should look like this:
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex {
display: flex;
}
.flex-column {
display: flex;
}
.item {
min-width: 0;
padding: 8px;
background-color: #fff;
overflow-wrap: break-word;
}
<div class="body">
<div class="flex">
<div class="flex">
<div class="flex">
<div class="flex-column">
<div class="item">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
As you may see, the flex container of our flex-column ignores the fact that its children can shrink very well. I do not understand why is it behaves that way. Could you explain this to me? Why is the flexbox-container doesn't respect its child flexbox min-width: 0?
The solution that I've found is to set min-width: 0 to all flexboxes in the hierarchy which looks very hacky and dangerous because I can break our application layout in unexpected places.
To understand this, simply add border with different colors to your items and you will see that you have overflow at different levels. More precesily, we have only one overflow that is moving to a lower lever after adding each min-width.
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex {
display: flex;
}
.flex-column {
display: flex;
}
.item {
padding: 8px;
background-color: #fff;
overflow-wrap: break-word;
}
<div class="body">
<div class="flex" style="border:5px solid red;">
<div class="flex" style="border:5px solid green;">
<div class="flex" style="border:5px solid blue;">
<div class="flex-column" style="border:5px solid yellow;">
<div class="item" style="border:5px solid pink;">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
</div>
</div>
</div>
Every min-width will fix one overflow, allow the element to shrink and move the overflow to next level. That's why you need a cascading min-width.
Adding one:
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex {
display: flex;
}
.flex-column {
display: flex;
}
.item {
padding: 8px;
background-color: #fff;
overflow-wrap: break-word;
}
<div class="body">
<div class="flex" style="border:5px solid red;">
<!-- adding min-width at this level -->
<div class="flex" style="border:5px solid green;min-width:0;">
<div class="flex" style="border:5px solid blue;">
<div class="flex-column" style="border:5px solid yellow;">
<div class="item" style="border:5px solid pink;">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Adding another:
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex {
display: flex;
}
.flex-column {
display: flex;
}
.item {
padding: 8px;
background-color: #fff;
overflow-wrap: break-word;
}
<div class="body">
<div class="flex" style="border:5px solid red;">
<div class="flex" style="border:5px solid green;min-width:0;">
<!-- adding min-width at this level -->
<div class="flex" style="border:5px solid blue;min-width:0">
<div class="flex-column" style="border:5px solid yellow;">
<div class="item" style="border:5px solid pink;">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
</div>
</div>
</div>
Again:
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex {
display: flex;
}
.flex-column {
display: flex;
}
.item {
padding: 8px;
background-color: #fff;
overflow-wrap: break-word;
}
<div class="body">
<div class="flex" style="border:5px solid red;">
<div class="flex" style="border:5px solid green;min-width:0;">
<div class="flex" style="border:5px solid blue;min-width:0">
<!-- adding min-width at this level -->
<div class="flex-column" style="border:5px solid yellow;min-width:0;">
<div class="item" style="border:5px solid pink;">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
</div>
</div>
</div>
The last one:
.body {
width: 300px;
border: 1px solid black;
padding: 8px;
background-color: #ccc;
}
.flex {
display: flex;
}
.flex-column {
display: flex;
}
.item {
padding: 8px;
background-color: #fff;
overflow-wrap: break-word;
}
<div class="body">
<div class="flex" style="border:5px solid red;">
<div class="flex" style="border:5px solid green;min-width:0;">
<div class="flex" style="border:5px solid blue;min-width:0">
<div class="flex-column" style="border:5px solid yellow;min-width:0;">
<!-- adding min-width at this level -->
<div class="item" style="border:5px solid pink;min-width:0">
This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
your example looking how you want it to look. But both values are being rendered correctly.
</div>
</div>
</div>
</div>
</div>
</div>
I have to design something like below:
A parent container with 'n' childs that may very well go beyond the
window's width and in that case page should scroll and not wrap to
next line.
The above container will be rendered multiple times below one
another.
The page should scroll as a whole, i.e. scroll should be at a wrapper
(div with class .overflow) level and not at individual parent
level.
Scroll horizontally in the snippet below to see the behavior.
.overflow {
overflow-x: auto;
}
.parent {
background: #ccc;
border: 4px solid blue;
display: flex;
margin: 10px 0;
}
.child {
display: inline-flex;
height: 50px;
background: white;
margin: 10px;
flex: 1 0 300px;
border: 2px solid red;
}
<div class="overflow">
<div class="parent">
<div class="child">
1
</div>
<div class="child">
2
</div>
<div class="child">
3
</div>
</div>
<div class="parent">
<div class="child">
1
</div>
<div class="child">
2
</div>
<div class="child">
3
</div>
</div>
</div>
The issue now is that the grey background on parent is not overflowing behind the children beyond the window's width.
How to achieve this (make .parent div background overflow for all its children) and possibly with retaining the flex-box?
Use inline-flex for parent and replace flex-basis by width
.overflow {
overflow-x: auto;
}
.parent {
background: #ccc;
border: 4px solid blue;
display: inline-flex;
min-width:100%; /*To keep the block behavior*/
box-sizing:border-box;
margin: 10px 0;
}
.child {
display: inline-flex;
height: 50px;
background: white;
margin: 10px;
width:300px;
flex-shrink:0;
flex-grow:1;
border: 2px solid red;
}
<div class="overflow">
<div class="parent">
<div class="child">
1
</div>
<div class="child">
2
</div>
<div class="child">
3
</div>
</div>
<div class="parent">
<div class="child">
1
</div>
<div class="child">
2
</div>
<div class="child">
3
</div>
</div>
</div>
Remove overflow div
Change your parent class css to
.parent {
overflow-x: auto;
background: #ccc;
border: 4px solid blue;
display: flex;
margin: 10px 0;
}
I am using a flex grid to lay out information. I want to highlight one of the cells within the grid so that it stands out to users by adjusting the height of the respective cell. However, my attempts have not gotten far as adjusting the properties of once cell will thereby affect the surrounding cells.
In my fiddle below, I have a class .highlighted within .flexbox-2 that I would like to change. Basically, the row 1 of the second column would have a taller height than the first and third column, but all the borders will still be aligned. I was thinking to apply position: absolute and change its CSS there, but this does not prove fruitful. I'm wondering if there are other routes I can take.
Check this jsfiddle
Code:
* {
box-sizing: border-box;
}
body {
font-family: helvetica, serif;
}
.container {
display: -webkit-flex;
-webkit-flex-direction: row;
}
.flex {
display: flex;
flex-direction: column;
}
.flex-row {
flex: 1;
border: 1px solid;
}
.flexbox-1 {
-webkit-flex: 1;
border: solid 3px red;
}
.flexbox-2 {
-webkit-flex: 1;
border: solid 3px green;
height: 200px;
margin-left: 10px;
position: relative;
}
.highlighted {
position: absolute;
border: 1px solid yellow;
padding-top: 20px;
}
.flexbox-3 {
-webkit-flex: 1;
border: solid 3px blue;
height: 200px;
margin-left: 10px;
}
<div class="container">
<div class="flex flexbox-1">
<div class="flex-row">row 1</div>
<div class="flex-row">row 2</div>
<div class="flex-row">row 3</div>
</div>
<div class="flex flexbox-2">
<div class="flex-row highlighted">row 1</div>
<div class="flex-row">row 2</div>
<div class="flex-row">row 3</div>
</div>
<div class="flex flexbox-3">
<div class="flex-row">row 1</div>
<div class="flex-row">row 2</div>
<div class="flex-row">row 3</div>
</div>
</div>
If you want that first row to stick out above the other two columns, you could use a negative margin-top:
.highlighted {
border: 1px solid yellow;
margin-top: -10px;
padding-bottom: 10px;
}
Working Example
I am trying to create this layout using only CSS:
When title fits:
When title doesn't fit:
The btn on the right should be centered if it wraps.
I tried this:
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
}
.block {
padding: 5px;
border: 1px solid orange;
float: left;
}
.right-block {
float: right;
}
<div class="container">
<div class="block">Logo</div>
<div class="block">Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
But obviously, the btn is still on the right after it wraps. Any idea how to center it when it wraps ? And I'd like to avoid javascript.
Fiddle here: http://jsfiddle.net/b7rvhwqg/
Pure CSS solution using a flexbox layout:
Updated Example Here
The trick is to add justify-content: center/flex-wrap: wrap to the parent .container element for horizontal centering. Then adjust the first element's margin-right value to auto in order to prevent the last element from being centered when it's on the same line.
(You may need to resize the browser to see how it adjusts).
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.logo-text {
display: flex;
margin-right: auto;
}
.block {
padding: 5px;
border: 1px solid orange;
}
.center-block {
white-space: nowrap;
margin-right: auto;
}
<div class="container">
<div class="logo-text">
<div class="block logo">Logo</div>
<div class="block text">This title is short.</div>
</div>
<div class="block right-block">right-btn</div>
</div>
<div class="container">
<div class="logo-text">
<div class="block logo">Logo</div>
<div class="block text">This title is slightly longer than the other one. This title is longer than the other one...</div>
</div>
<div class="block right-block">right-btn</div>
</div>
There is an issue to achieve this via Pure CSS. The div is already having a float and you want to have a "long title" to accommodate that float and at the same time, you want the other right float to jump and become center. This is currently not possible. I believe, you need to consider media queries, but again, that will be a dependent solution, but your title looks like independent of expanding/contracting.
is it ok for you if the title will just fit depending on what width u want?.. for example:
{Logo}Title is toooooooooooooooooooooooooooooooooolong {btn}
it will become like this:
{Logo}Title is tooo... {btn}
it will be cut, then only ". . ." will continue
Flexbox is the most suitable for this task:
<div class="container">
<div class="block logo">Logo</div>
<div class="block title">Title that is too long Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
.container {
display: flex;
flex-wrap: wrap;
width: 100%
border: 1px solid grey;
}
.block.logo {
flex-grow: 1;
border: 1px solid orange;
}
.block.title{
flex-grow: 10;
border: 1px solid orange;
}
.right-block {
flex-grow: 1;
border: 1px solid orange;
text-align: center;
}
http://jsfiddle.net/gmrash/7b8w982t/
.container {
width: 100%;
border: 1px solid grey;
padding: 5px;
}
.block {
padding: 5px;
border: 1px solid orange;
float: left;
}
.ellipsis{
text-overflow: ellipsis;
/* Required for text-overflow to do anything */
white-space: nowrap;
overflow: hidden; width: 75%;
}
.right-block {
float: right;
}
<div class="container">
<div class="block">Logo</div>
<div class="block ellipsis">Title that is too long Title that is too long Title that is too long that is too long Title that is too long</div>
<div class="block right-block">right-btn</div>
<div style="clear: both"></div>
</div>
jsFiddle