html/css - create self expanding dynamic div - html

I have sample div structure:
<div id="outer" style="width:600">
<div class="inner"></div> <!--row1-->
<div class="inner"></div>
<div class="inner"></div><br/>
<div class="inner"></div> <!--row2-->
<div class="inner"></div>
</div>
Outer div has fixed width. Inner divs are generated dynamically, so there could be 1,2,3 etc divs per row.
Is it possible to resize (maybe in clear css?) inner divs according to number per row?
So, in example first row divs would have 200px width and in second row 300px width.

You can do this with display: table-cell. Browser support: http://caniuse.com/css-table
See: http://jsfiddle.net/thirtydot/x5ZFg/
HTML: (changed slightly from your question)
<div id="outer">
<div class="innerWrap"> <!--row1-->
<div class="inner"></div>
<div class="inner"></div>
<div class="inner"></div>
</div>
<div class="innerWrap"> <!--row2-->
<div class="inner"></div>
<div class="inner"></div>
</div>
</div>
CSS:
#outer {
width: 600px
}
.innerWrap {
width: 100%;
display: table;
table-layout: fixed
}
.inner {
display: table-cell;
height: 50px;
border: 1px dashed #f0f
}

Related

Last row in CSS Grid where cells have a footer and are stretched to same height drawing strangely

I have a code pen at https://codepen.io/james-hudson3010/pen/wveJqXd
What I am looking to achieve is the following:
I have an arbitrary number of cells. This example only uses 10, but it could be more or less than 10
Each cell has a footer which needs to be aligned to the bottom of cell so that they are aligned across cells in the same row
The height of a cell can vary, but the height needs to be stretched so every cell in the same row has the same height to support #2
This almost works perfectly using Safari ( Version 14.1.2 (15611.3.10.1.5, 15611) ), but the last cell in the last row is wider than it should be.
The behavior is worse in Chrome ( Version 93.0.4577.63 (Official Build) (x86_64) ). The rows are drawn higher than they should be. The last cell in the last row is to wide.
Is this due to a lack of complete browser support?
If this is due to not specifying my css correctly, what do I need to do?
.example1 {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
align-items: stretch;
}
div {
border: solid 1px;
padding: 1rem;
}
.contentdiv {
background-color: red;
display: table;
height: 100%;
width: 100%;
}
.foot {
display: table-row;
vertical-align: bottom;
height: 1px;
}
<div class="example1">
<div class="contentdiv">1<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">2
<div class="foot">bottom</div>
</div>
<div class="contentdiv">3
<div class="foot">bottom</div>
</div>
<div class="contentdiv">4
<div class="foot">bottom</div>
</div>
<div class="contentdiv">5a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">6
<div class="foot">bottom</div>
</div>
<div class="contentdiv">7a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">8
<div class="foot">bottom</div>
</div>
<div class="contentdiv">9
<div class="foot">bottom</div>
</div>
<div class="contentdiv">10a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
</div>
This has to do with the setting the display to table for the contentdiv - and setting it's width and height to 100%.
Basically what is happening - if you view your elements in the web inspector - you'll see that all of your elements are wider than 300px because of the padding 1rem, so they are actually overlapping already, you just can't visually see it until the last row.
You can avoid this setting, * { box-sizing: border-box } and the display to flex instead, and using the justify-content property to keep the foot aligned on all rows:
* {
box-sizing: border-box;
}
.example1 {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
align-items: stretch;
}
div {
border: solid 1px;
padding: 1rem;
}
.contentdiv {
background-color: red;
display: flex;
flex-direction: column;
justify-content: space-between;
/* Avoid the borders stacking */
margin: -1px;
}
<div class="example1">
<div class="contentdiv">1<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">2
<div class="foot">bottom</div>
</div>
<div class="contentdiv">3
<div class="foot">bottom</div>
</div>
<div class="contentdiv">4
<div class="foot">bottom</div>
</div>
<div class="contentdiv">5a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">6
<div class="foot">bottom</div>
</div>
<div class="contentdiv">7a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">8
<div class="foot">bottom</div>
</div>
<div class="contentdiv">9
<div class="foot">bottom</div>
</div>
<div class="contentdiv">10a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
</div>
From my comment,
display:table is not a good idea here (table-layout:fixed would be required for the width) and height : 1px (expanded cause of the table-layout display) is also not a good idea, while flex or grid will do this without sides effects minus the box-sizing:border-box missing to mind height:100% and padding/ border.To set that element at the bottom, flex or grid should be the way to IMHO
here is an example with grid instead table for display ;)
.example1 {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
align-items: stretch;
}
div {
border: solid 1px;
padding: 1rem;
box-sizing:border-box;
}
.contentdiv {
background-color: red;
display: grid;
height: 100%;
}
.foot {
margin-top:auto;/* push it all the way down */
}
<div class="example1">
<div class="contentdiv">1<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">2
<div class="foot">bottom</div>
</div>
<div class="contentdiv">3
<div class="foot">bottom</div>
</div>
<div class="contentdiv">4
<div class="foot">bottom</div>
</div>
<div class="contentdiv">5a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">6
<div class="foot">bottom</div>
</div>
<div class="contentdiv">7a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
<div class="contentdiv">8
<div class="foot">bottom</div>
</div>
<div class="contentdiv">9
<div class="foot">bottom</div>
</div>
<div class="contentdiv">10a<br/>a<br/>a<br/>
<div class="foot">bottom</div>
</div>
</div>
Not clear about the requirement you have put in ,if you are expecting this ()
Also you can better play around with flex property which is easier
grid image sample
if so I just changed the height in class contentdiv to inherit.

Remove redundant space at bottom when using Angular Flex with "row wrap" and grid-gap

I'm using Angular Flex to align cards in a row. The cards should wrap into a new line if there are several of them. The relevant settings of the block are
fxLayout="row wrap" fxLayoutGap="40px grid"
fxLayoutGap uses paddings on the inner elements and a negative margin on the container so that the gap is also applied when the inner elements wrap to a new row. So I do not want to remove the grid setting (or the paddings or negative margins in the
In addition, the cards are grouped into blocks with a header and a line on the left. I've created a sample that mirrors the settings that Angular Flex applies. The image is taken from this sample:
As you can see, there is redundant space at the bottom of each group. I want the block and the line on the left to end where the last row of cards (of the block) ends:
You can find the sample on jsfiddle.
How can I adjust the CSS and/or the Angular Flex settings to remove the redundant space and make the line end at the last row of cards while preserving the space between the blocks?
remove the padding-bottom from the last two elements:
#outer {
border-left: 2px solid red;
padding-left: 0px;
padding-bottom: 40px;
}
#outer:not(:first-child) {
margin-top: 40px;
}
#header {
padding: 10px;
margin: 0px 0px 40px 0px;
background-color: red;
}
#container {
margin: 40px -40px -40px 40px;
display: flex;
flex-flow: row wrap;
box-sizing: border-box;
}
#inner {
padding: 0px 40px 40px 0px;
flex: 0 0 50%;
box-sizing: border-box;
max-width: 50%;
min-width: 50%;
}
/* added */
#inner:last-child,
#inner:nth-last-child(2):nth-child(odd){
padding-bottom:0;
}
/**/
#card {
background-color: green;
}
<div id="outer">
<div id="header">
HEADER
</div>
<div id="container">
<div id="inner">
<div id="card">
CARD
</div>
</div>
<div id="inner">
<div id="card">
CARD
</div>
</div>
<div id="inner">
<div id="card">
CARD
</div>
</div>
<div id="inner">
<div id="card">
CARD
</div>
</div>
</div>
</div>
<div id="outer">
<div id="header">
HEADER
</div>
<div id="container">
<div id="inner">
<div id="card">
CARD
</div>
</div>
<div id="inner">
<div id="card">
CARD
</div>
</div>
</div>
</div>
<div id="outer">
<div id="header">
HEADER
</div>
<div id="container">
<div id="inner">
<div id="card">
CARD
</div>
</div>
</div>
</div>
<div id="outer">
<div id="header">
HEADER
</div>
<div id="container">
<div id="inner">
<div id="card">
CARD
</div>
</div>
<div id="inner">
<div id="card">
CARD
</div>
</div>
<div id="inner">
<div id="card">
CARD
</div>
</div>
</div>
</div>

Why is 'max-width' ignored onto table-cell?

Why does the max-width get ignored in the following table, once I add display: table-row-group to header and body?
.table {
display: table;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
padding: 5px;
border: 1px solid black;
}
.header,
.body {
display: table-row-group;
}
<div class="table">
<div class="header">
<div class="row">
<div class="cell" style="max-width: 4em;">
content content content content content
</div>
<div class="cell">
content
</div>
</div>
<div class="row">
<div class="cell">
content content content content content
</div>
<div class="cell">
content
</div>
</div>
</div>
<div class="body">
<div class="row">
<div class="cell">
content
</div>
<div class="cell">
content
</div>
</div>
</div>
</div>
I want to control the min/max-size of cells into body, setting min-/max-width on the head cells (that doesn't necessarily need two rows as in the snippet).
What is happening here? What prevents the max-width to work?
“the effect of 'min-width' and 'max-width' on tables, inline tables, table cells, table columns, and column groups is undefined.” See definition of max-width in the CSS 2.1 spec.

endless horizontal stretch with unknown width of children

What I'm trying to do is to create div which can expand endlessly to the right.
This is quite easy, there is a couple of working examples.
However, I have trouble with adapting from:
<div id="container">
<div class="item"></div>
<div class="item"></div>
...
</div>
To the design I'm using:
<div id="container">
<div class="project">
<div class = "textContainer">text Container 1.1 </div>
<div class = "imgContainer">img Container 1.1 </div>
...
</div>
<div class="project">
<div class = "textContainer">text Container 2.1 </div>
<div class = "imgContainer">img Container 2.1 </div>
<div class = "imgContainer">img Container 2.2 </div>
<div class = "imgContainer">img Container 2.3 </div>
...
</div>
</div>
Where textContainer and imgContainer are specialized classes to contain the obvious(Important note: I want the imgContainer to fill 100% of height and adjust horizontally to keep aspect-ratio).
To give better idea of my intentions (almost) working fiddle. Remove the comment in container to see desired effect.
Remove the floats. Convert all children to inline-blocks, and set white-space: nowrap on the .container and sub containers (.project). This will force everything to a single line, and will make the width of the container fit his children.
#container {
height: calc(100vh - 100px);
margin: 40px 0;
white-space: nowrap;
}
.project {
white-space: nowrap;
background: blue;
}
.textContainer {
width: 200px;
background: red;
}
.project, .imgContainer, .textContainer {
display: inline-block;
height: 100%;
vertical-align: top;
}
<div id="container">
<div class="project">
<div class="textContainer">text Container 1.1 </div>
<div class="imgContainer">img Container 1.1 </div>
<div class="imgContainer">img Container 1.2 </div>
<div class="imgContainer">img Container 1.3 </div>
</div>
<div class="project">
<div class="textContainer">text Container 2.1 </div>
<div class="imgContainer"><img src="http://myhswm.org/images/sized/images/animals/anjo-256x256.jpg"></div>
<div class="imgContainer">img Container 2.2 </div>
<div class="imgContainer">img Container 2.3 </div>
<div class="imgContainer">img Container 2.4 </div>
</div>
</div>

How to use Flexbox?

I have a layout like this:
<div class="outer">
<div class="inner"></div>
<div class="inner"></div>
<div class="inner">
<div class="deeper">
<div class="newLineContent"></div>
<div class="newLineContent"></div>
<div class="newLineContent"></div>
</div>
</div>
</div>
<div class="outer">
<div class="inner"></div>
<div class="inner"></div>
<div class="inner">
<div class="deeper">
<div class="newLineContent"></div>
<div class="newLineContent"></div>
<div class="newLineContent"></div>
</div>
</div>
</div>
I have to align the divs like: All the divs with "outer" class has to start from new line and all the divs with "inner" class has to be in the same line within "outer" div and the divs with deeper class inside "outer" div should start from new line and the "newLineContent" divs has to be in the same line within "deeper" divs
How can I achieve this using flexbox? or is there any other way to achieve it?
One can do similar without Flexbox, thought Flexbox appears to be the best in this case.
.outer,
.deeper {
display: flex;
flex-wrap: wrap;
}
.inner {
flex-grow: 1;
padding: 20px 10px;
border: 1px solid white;
background: lightgray;
}
.inner:last-child {
flex-basis: 100%;
}
.newLineContent {
flex-grow: 1;
padding: 10px;
border: 1px solid white;
background: lightgray;
}
<div class="outer">
<div class="inner"></div>
<div class="inner"></div>
<div class="inner">
<div class="deeper">
<div class="newLineContent"></div>
<div class="newLineContent"></div>
<div class="newLineContent"></div>
</div>
</div>
</div>
<div class="outer">
<div class="inner"></div>
<div class="inner"></div>
<div class="inner">
<div class="deeper">
<div class="newLineContent"></div>
<div class="newLineContent"></div>
<div class="newLineContent"></div>
</div>
</div>
</div>
Updated based on a comment
If the deeper can be a child to any of the inner, and to achieve similar result, one would need either a parent selector, which doesn't exist, or give the inner an additional class for those that contain a deeper.
Another possible workaround could be to use viewport units vw.
.outer,
.deeper {
display: flex;
flex-wrap: wrap;
width: calc(100vw - 40px); /* 40px to make up for body's margins/scrollbar */
margin: 0 auto;
}
.inner {
flex-grow: 1;
padding: 20px 10px;
border: 1px solid white;
background: lightgray;
}
.deeper {
width: calc(100vw - 62px); /* 62px is to make up for "inner" padding/border, 22px,
and 40px for body's margins/scrollbar */
}
.newLineContent {
flex-grow: 1;
padding: 10px;
border: 1px solid white;
background: lightgray;
}
<div class="outer">
<div class="inner"></div>
<div class="inner"></div>
<div class="inner">
<div class="deeper">
<div class="newLineContent"></div>
<div class="newLineContent"></div>
<div class="newLineContent"></div>
</div>
</div>
</div>
<div class="outer">
<div class="inner"></div>
<div class="inner">
<div class="deeper">
<div class="newLineContent"></div>
<div class="newLineContent"></div>
<div class="newLineContent"></div>
</div>
</div>
<div class="inner"></div>
</div>
.outer{
display: flex;
}
Simple as that! How you configure parent and child options, depends on the effect you want to achieve.
You can do it with Flexbox:
.outer {
display: flex; /* displays flex-items (children) inline */
justify-content: space-between; /* MDN: The items are evenly distributed within the alignment container along the main axis. The spacing between each pair of adjacent items is the same. */
}
.inner:last-child .deeper {
display: flex;
}
<div class="outer">
<div class="inner">1.1</div>
<div class="inner">1.2</div>
<div class="inner">1.3
<div class="deeper">
<div class="newLineContent">1.3.1</div>
<div class="newLineContent">1.3.2</div>
<div class="newLineContent">1.3.3</div>
</div>
</div>
</div>
<div class="outer">
<div class="inner">2.1</div>
<div class="inner">2.2</div>
<div class="inner">2.3
<div class="deeper">
<div class="newLineContent">2.3.1</div>
<div class="newLineContent">2.3.2</div>
<div class="newLineContent">2.3.3</div>
</div>
</div>
</div>
With your current HTML structure this is the result you get. Flex-items of the .inner:last-child .deeper div can't stretch the full width of the browser because the .deeper div represents one third of the parent element, i.e. the .outer div.