Flexbox under overflow not taking full width - html

I've simplified my HTML/CSS in a jsfiddle of what I'm trying to achieve without success.
I cannot make the .problem take full width. The content is represented by the blue background while the box itself is red.
I'm trying to make all the scrollable content have full width and a blue background since I guess the background not appearing after the scrollable content is a problem of width.
What I've taken a look so far:
Flexbox not full width
Flexbox: how to get divs to fill up 100% of the container width without wrapping?
Fill 100% width of scrolling flex container
To clarify: giving .problem a fixed width does give me the effect I want but not the solution since the content is dynamic and I cannot know its width.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
}
html,
body {
width: 100%;
height: 100%;
}
.bg {
display: flex;
background-color: gray;
width: 100%;
height: 100%;
}
.usable {
display: flex;
height: 90%;
width: 100%;
background-color: white;
}
.box {
position: absolute;
top: 0;
left: 0;
height: 200px;
width: 300px;
display: flex;
align-items: flex-start;
align-content: flex-start;
flex-direction: column;
background-color: red;
}
.top {
display: flex;
height: 20px;
background-color: yellow;
width: 100%;
}
.bottom {
width: 100%;
flex: 0 1 100%;
overflow: auto;
}
.contents {
height: 100%;
display: flex;
flex-direction: column;
}
.forms {
flex: 0 1 100%;
}
.problem {
display: flex;
height: 100%;
background-color: blue;
}
.row {
display: flex;
align-items: center;
}
.cell {
align-self: stretch;
flex: 1 0 100px;
}
<div class="bg">
<div class="usable">
<div class="box">
<div class="top">
Top
</div>
<div class="bottom">
<div class="contents">
<div class="forms">
<div class="problem">
<div class="data">
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 00:21:06</div>
<div class="cell">test1</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:26</div>
<div class="cell">test2</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:26</div>
<div class="cell">test3</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test4</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test5</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test6</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test7</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:58</div>
<div class="cell">test8</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:58</div>
<div class="cell">test9</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:43:11</div>
<div class="cell">test10</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

The problem is that the container with the blue background is taking the width of the parent and not the content, to solve this you can change its property "display" to "inline-flex".
Then if you change the "flex" property of the .cell class to a "width" property the width you set will count for the parent and it will reach the blue container making it fill all the content.
.problem {
display: inline-flex;
height: 100%;
background-color: blue;
}
.cell {
align-self: stretch;
width: 100px;
}

To allow elements to grow according to content, you can replace 'width' by 'min-width'.
This makes sure your box is a certain size for styling purposes but allows it to grow.
Then you can use 'max-width' to limit the amount it can grow.
So, change 'width: 100%' by 'min-width: 100%'.
You can find more here: https://css-tricks.com/boxes-fill-height-dont-squish/

Related

Align matching content in separate containers depending on width of largest content

I'm aware of CSS Subgrid being able to solve a layout like this, but what I'm looking to achieve is a list of containers with content inside. The content inside the containers is aligned right in the containers, but all the content is aligned (left) to the longest content.
Is this possible with flex? Are there any strategies to achieve this?
I suppose the HTML structure would be something like:
<div class="container">
<div class="content" style="100px"></div>
</div>
<div class="container">
<div class="content" style="300px"></div>
</div>
<div class="container">
<div class="content" style="400px">All other content aligned to this longest content</div>
</div>
<div class="container">
<div class="content" style="200px"></div>
</div>
It is most definitely doable with flex.
What I've done is create 2 columns inside the .container element. Column 2 will be right aligned inside the container, and your .content will be left aligned inside .column2.
All you need to do to adjust the alignment of the content inside the containers, is to play around with the widths of .column1 and .column2 in the snippet below:
* {
font-family: sans-serif;
}
.container {
display: flex;
background: lightgray;
align-items: center;
border-radius: 5px;
margin-bottom: 10px;
padding: 7px;
}
.content {
display: flex;
align-items: center;
padding: 0 10px;
background: #666;
border-radius: 5px;
color: white;
height: 50px;
}
.column1 {
width: 30%;
}
.column2 {
width: 70%;
}
<div class="container">
<div class="column1">Container</div>
<div class="column2">
<div class="content" style="width: 100px"></div>
</div>
</div>
<div class="container">
<div class="column1">Container</div>
<div class="content" style="width: 250px"></div>
</div>
</div>
<div class="container">
<div class="column1">Container</div>
<div class="column2">
<div class="content">All other content aligned to this longest content</div>
</div>
</div>
<div class="container">
<div class="column1">Container</div>
<div class="column2">
<div class="content" style="width: 200px"></div>
</div>
</div>

css - using grid-auto-column to create dynamic widths

I'm trying to get my css grid to either be 2 blocks per row (if there are enough items) or a single block that spans the entire width. However, I can't seem to get it to work using grid-auto-column.
The top block is what I want it to look like, and the bottom block is what my current css is creating.
.flex1 {
display: flex;
flex-direction: row;
flex: 1;
}
.grid1 {
display: grid;
grid-auto-columns: minmax(50%, 100%);
}
div.height {
height: 50px;
width: 100%;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
}
<div class="flex1">
<div class="red height">
</div>
<div class="blue height">
</div>
</div>
<div>
<div class="green height">
</div>
</div>
<br><br>
<div class="grid">
<div class="red height">
</div>
<div class="blue height">
</div>
<div class="green height">
</div>
</div>
Unfortunately, as far as I know, this isn't possible with the Grid, but it's a perfect and easy job for Flexbox, since you only need to handle one or single dimensional layout, in your case rows.
Below I'm giving you the shorter version of the desired result / behavior of flex-items, with less markup and styling:
.flex {
display: flex;
flex-wrap: wrap; /* enables wrapping of flex-items */
}
.flex > div {
flex: 1 0 50%; /* grows full width if alone in a row / doesn't shrink / initial width set to 50%, i.e. can't be less than 50% of the parent's width */
height: 50px;
}
.red {background: red}
.blue {background: blue}
.green {background: green}
.yellow {background: yellow}
<div class="flex">
<div class="red"></div>
</div>
<br>
<div class="flex">
<div class="red"></div>
<div class="blue"></div>
</div>
<br>
<div class="flex">
<div class="red"></div>
<div class="blue"></div>
<div class="green"></div>
</div>
<br>
<div class="flex">
<div class="red"></div>
<div class="blue"></div>
<div class="green"></div>
<div class="yellow"></div>
</div>
Use grid-template-areas: "a b" "c c";(change .grid1 to .grid as in html)
Also set grid-area:; to each div inside .grid
.flex1 {
display: flex;
flex-direction: row;
flex: 1;
}
.grid {
display: grid;
grid-auto-columns: minmax(50%, 100%);
grid-template-areas: "a b" "c c";
}
div.height {
height: 50px;
width: 100%;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
}
<div class="flex1">
<div class="red height">
</div>
<div class="blue height">
</div>
</div>
<div>
<div class="green height">
</div>
</div>
<br><br>
<div class="grid">
<div class="red height" style="grid-area: a;">
</div>
<div class="blue height" style="grid-area: b;">
</div>
<div class="green height" style="grid-area: c;">
</div>
</div>

Flexbox based table

I want to build a table with multiple columns with dynamic data. This leads to inability to use base <table> since it would change its columns width when content changes. Also I need to implement an option to hide some columns via JS.
Therefore I've decided to build a flexbox based table. However, I struggle with how to deal with column width when I hide some columns.
For example I have next table
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 100%;
min-height: 200px;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.table-head {
color: #a4a;
font-weight: 500;
}
.table-cell {
padding: 10px;
flex-grow: 1;
width: 100%;
overflow: hidden;
}
.table-cell:nth-child(1) {
width: 20%;
}
.table-cell:nth-child(2) {
width: 10%;
}
.table-cell:nth-child(3) {
width: 30%;
}
.table-cell:nth-child(4) {
width: 20%;
}
.table-cell:nth-child(5) {
width: 20%;
}
<div class="table">
<div class="row">
<div class="table-cell table-head">
Name
</div>
<div class="table-cell table-head">
Phone number
</div>
<div class="table-cell table-head">
Email
</div>
<div class="table-cell table-head">
Address
</div>
<div class="table-cell table-head">
Country
</div>
</div>
<div class="row">
<div class="table-cell">Peter</div>
<div class="table-cell">123123</div>
<div class="table-cell">peter#example.com</div>
<div class="table-cell">asdsad</div>
<div class="table-cell">empty</div>
</div>
<div class="row">
<div class="table-cell">Bob</div>
<div class="table-cell">123124</div>
<div class="table-cell">bob#bob.com</div>
<div class="table-cell">sadsads</div>
<div class="table-cell">empty</div>
</div>
</div>
And I want to hide 4th column. Since there some extra space has been created the rest columns should take it and become bigger.
How do I make columns to take their width and have some ratio? For example the address column should be bigger than country column. Also there could be a case when there is only one column left so that it should take 100% width.
I've tried to use flex-grow to make width, however I ended up with the problem that my columns even are not equal (head row had its own proportions and body it own) thus even no table layout when there is no columns hidden.
use flex:1 or 2, 3,... instead of width
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 100%;
min-height: 200px;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.table-head {
color: #a4a;
font-weight: 500;
}
.table-cell {
padding: 10px;
flex:1;
overflow: hidden;
}
.table-cell:nth-child(1) {
flex:3;
}
.table-cell:nth-child(2) {
flex:3;
}
.table-cell:nth-child(3) {
flex:3;
}
.table-cell:nth-child(4) {
flex:6;
}
.table-cell:nth-child(5) {
flex:2;
}
<div class="table">
<div class="row">
<div class="table-cell table-head">
Name
</div>
<div class="table-cell table-head">
Phone number
</div>
<div class="table-cell table-head">
Email
</div>
<div class="table-cell table-head">
Address
</div>
<div class="table-cell table-head">
Country
</div>
</div>
<div class="row">
<div class="table-cell">Peter</div>
<div class="table-cell">123123</div>
<div class="table-cell">peter#example.com</div>
<div class="table-cell">asdsad</div>
<div class="table-cell">empty</div>
</div>
<div class="row">
<div class="table-cell">Bob</div>
<div class="table-cell">123124</div>
<div class="table-cell">bob#bob.com</div>
<div class="table-cell">sadsads</div>
<div class="table-cell">empty</div>
</div>
</div>
i remove fourth table-cell with jquery:
$(document).ready(function(){
$('.table-cell:nth-child(4)').fadeOut(1000);
})
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 100%;
min-height: 200px;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.table-head {
color: #a4a;
font-weight: 500;
}
.table-cell {
padding: 10px;
flex:1;
overflow: hidden;
}
.table-cell:nth-child(1) {
flex:3;
}
.table-cell:nth-child(2) {
flex:3;
}
.table-cell:nth-child(3) {
flex:3;
}
.table-cell:nth-child(4) {
flex:6;
}
.table-cell:nth-child(5) {
flex:2;
}
<div class="table">
<div class="row">
<div class="table-cell table-head">
Name
</div>
<div class="table-cell table-head">
Phone number
</div>
<div class="table-cell table-head">
Email
</div>
<div class="table-cell table-head">
Address
</div>
<div class="table-cell table-head">
Country
</div>
</div>
<div class="row">
<div class="table-cell">Peter</div>
<div class="table-cell">123123</div>
<div class="table-cell">peter#example.com</div>
<div class="table-cell">asdsad</div>
<div class="table-cell">empty</div>
</div>
<div class="row">
<div class="table-cell">Bob</div>
<div class="table-cell">123124</div>
<div class="table-cell">bob#bob.com</div>
<div class="table-cell">sadsads</div>
<div class="table-cell">empty</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>

Center align HTML Elements, while adding new items from left

I have a parent div containing an unknown number of smaller divs that are used like large icon-like buttons. If a row of child divs is full, I would like them to have equal margins on each side (ie. centered), but if a row is not full I would like them to be filled in from the left side (but still in columns with the elements above). Is there a way to do this with CSS? Resizing the window should maintain the centering and add/remove columns as necessary. All the child div widths are known.
Here's a crappy image of the behavior I'm trying for:
Okay I figured out a solution for this that both allows for equal margins and ALSO aligns divs left in the last row. The caveat is that it uses hidden elements, so the container is taller than the visible elements it contains.
Also it adds a bunch of extra markup to your code. If I thought of any other way to do this, I would do it differently. Sorry.
JSFiddle: https://jsfiddle.net/88qadmo3/2/
#container > div {
margin: 10px;
width: 100px;
height: 100px;
}
.floatleft {
background-color: red;
}
.invis {
visibility: hidden;
}
#container {
display: flex;
flex-wrap: wrap;
justify-content: center;
background-color: #DDDDDD;
}
.clearfix {
clear: both;
}
<div id="outer">
<div id="container">
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
</div>
</div>
You can do this by wrapping each of the child elements in an element and using CSS media queries to change the size of the wrappers. Then, just use % width on the wrappers based on what you want the column sizes to be.
When you run the example, shrink it to <400px so you can see it move from 6 columns to 3 (you'll need to run the code snippet on a full-page to see this).
.parent {
border: 2px solid red;
}
.child {
width: 100px;
display: block;
margin: 0 auto;
border: 1px solid black;
}
.wrapper {
display: inline-block;
text-align: center;
float: left;
width: 16.66%;
margin: 0;
padding: 0;
box-sizing: border-box;
}
.clear {
clear: both;
}
#media (max-width: 800px) {
.wrapper {
width: 20%;
}
}
#media (max-width: 600px) {
.wrapper {
width: 25%;
}
}
#media (max-width: 400px) {
.wrapper {
width: 33.33%;
}
}
<div class="parent">
<div class="wrapper">
<div class="child">1</div>
</div>
<div class="wrapper">
<div class="child">2</div>
</div>
<div class="wrapper">
<div class="child">3</div>
</div>
<div class="wrapper">
<div class="child">4</div>
</div>
<div class="wrapper">
<div class="child">5</div>
</div>
<div class="wrapper">
<div class="child">6</div>
</div>
<div class="clear"></div>
</div>
Just use float left, and items of the width (the original fiddle):
<div class="container">
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
</div>
.container {
overflow: auto;
}
.item {
width: 50px;
float: left;
margin: 0 10px;
}

Alternating grid colours

I'm wanting to achieve a two column grid layout that has grid blocks with alternating colours. However, achieving this with a simple nth-child(odd) or nth-child(even)won't do the trick.
I'm pretty sure what I want can be achieved using a touch of nth-child trickery, rather than a JS solution, but not quite sure how.
Here's a pen of what I'm wanting to achieve: http://codepen.io/abbasinho/pen/Gbnze
Here's the HTML as it is in the pen, i'd like to avoid the additional class to add the colors:
<div class="grid-holder">
<div class="grid red"></div>
<div class="grid blue"></div>
<div class="grid blue"></div>
<div class="grid red"></div>
<div class="grid red"></div>
<div class="grid blue"></div>
<div class="grid blue"></div>
<div class="grid red"></div>
</div>
SASS:
.grid-holder {
width: 50%;
margin: 0 auto;
overflow: hidden;
}
.grid {
width: 50%;
height: 200px;
float: left;
&.red {
background: red;
}
&.blue {
background: blue;
}
}
As you repeat a pattern every 4 elements (red/blue/blue/red), you can achieve this with :nth-child(4n+x) variations :
<div class="grid-holder">
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
<div class="grid"></div>
</div>
.grid-holder {
width: 50%;
margin: 0 auto;
overflow: hidden;
}
.grid {
width: 50%;
height: 200px;
float: left;
background: red;
// The 2nd and the 3rd element in our pattern will be blue
&:nth-child(4n+2),
&:nth-child(4n+3) {
background: blue;
}
}