Container height equal to it's overlapping children with dynamic heights - html

Consider you are a block container with fixed width, height: auto and two elements inside of you. Each element has it's own height based on the number of items inside it. Now, you want your children to be positioned at the top, overlapping each other. But, at the same time you want your height to be equal to the height of the child with the most items.
Do you think you can handle it on your own, without asking that weird JS wizardly-guy to look after you and your children?
Also, your children seems to like dynamically changing the number of items inside of them, so you sadly can't use fixed heights here.
Desired result:
(each item is translated to the left a bit for better view)
Yay, some code!
<div class="container">
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
</div>
.container {
width: 300px;
}
.menu {
}
.item {
height: 30px;
}
👨‍💻 JSFiddle with example

Yes, you can do this! If you are a CSS grid.
According to the specs, if you put two elements in the same cell. they will overlap each other and with align-items: start; you can align items by their tops.
<div class="container">
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
<div class="child">
<div class="item"></div>
<!-- ... -->
</div>
</div>
/** Creating a CSS grid with a single cell */
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
grid-template-areas: 'cell';
align-items: start;
}
/** Putting both children in the first cell */
.child {
grid-area: cell;
}
.item {
height: 30px;
}
And here's the updated JSFiddle to demonstrate the solution.
CSS grid has a pretty good browser coverage. Make sure to use autoprefixer for IE though.
If you know another/better approach, please add it as well, I'm sure it will be useful.

Related

How can I make my CSS grid even with the background color?

I have been trying to make an even 3x2 grid. Some of the blocks are longer and the others and I want them all to be the same length. What would be the best CSS practice to accomplish that? The pictures is what I've accomplished so far.
HTML
<div class="column col-lg-4 col-md-6 col-sm-6 col-xs-12">
<div class="service-block-two single-item" id="service_pest">
<div class="inner-box">
<div class="content">
<div class="clearfix top-area">
<div class="text">
<h4>Insect Control</h4>
</div>
</div>
<p>Insect control is an on going maintenance issue on Nantucket. We recommend foundation treatments 2-3 times per year to keep all kinds of insects at bay. Ants, pill bugs, earwigs and a whole host of other insects can be a nuisance, let us deal with them so you don't have too.
</p><br>
<div class="link">More Details</div>
</div>
</div>
</div>
</div>
CSS
.service-block-two{
position:relative;
margin-bottom: 100px;
background-color: #f7f7f7f7;
padding-top: 35px;
padding-bottom: 35px;
}
.service-block-two .content p {
text-align: center;
width: auto;
}
.service-block-two .content .link {
text-align: center;
}
CSS grid is a great option and works well, where supported.
If browser support is a concern, you can also use flexbox which has slightly better support. Regardless of which, you'll need vendor prefixes.
Code Pen example: https://codepen.io/anon/pen/GeQREE
CSS changes are fairly straight forward. Parent/wrapping elements would need the following:
display: flex;
flex-wrap: wrap;
The simplest change for the children would be a width. Something like:
width: 31%;
margin: 1%;
(Total width would be 33% or 3 across)
Hope this helps!
Grid support: https://caniuse.com/#feat=css-grid
Flex support: https://caniuse.com/#feat=flexbox
you can achieve this very easily with the new css grid feature. browser support is quite good. you might need to add vendor prefixes to have maximum browser support.
Basically, you need a parent div which holds/wraps its children (for your case that would be the grey boxes).
suppose this is the HTML:
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
and the css to make this a 3(column)x2(row) grid would be:
.parent {
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(2,1fr);
grid-gap: 15px;
}
.child {
background: #f7f7f7;
padding: 15px;
}
All columns in a row will be of same height and equal to the tallest column. Here is a working codepen link to see it in action.

Zurb Foundation 6 XY Grid using Grid Container within Flex-Container

I am using ZURB foundation 6 with XY grid and have run into a little problem and most likely something I'm doing wrong.
I want to center elements vertically so I use
<div class="flex-container">
<div class="grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>
And using jQuery I set the height of flex-container by using windowHeight = $(window).innerHeight();
Voila the items are vertically aligned... However two issues arise from this:
small-6 cell has a width of 50% that is not being respected and shrinks down to the approx length of the text.
flex-container unlike grid-container does not have a width or padding.
To resolve the issue I added some CSS like so:
.flex-container .align-middle {
max-width: 62.5rem;
margin: 0 auto;
width: 100%;
}
So while I've patched the issue I can't help thinking that there must be an easier way, a proper way using just classes. It seems odd that grid-container is setup to do so but flex-container is not.
The main problem here is that with flex-container, the grid-x element will, along being a flex container of its own, also become a flex row item, having the default flex item value 0 1 auto.
This means the grid-x won't grow wider than its content, hence width: 50% won't work on its children (small-6), as their parent doesn't have a width set.
By adding e.g. flex-child-grow or cell to the grid-x element, it will fill its parent's width, and the inner flex items will start behave as expected.
Note 1: With grid-container this is not needed since it is not a flex container, where the grid-x is a normal div, displayed as flex, which, like a block element, by default take full width of its parent.
Note 2: Both flex-container and grid-container does have a default width of 100%, it is the grid-x, when being a flex item, that cause the issue not taking its parent's width by default.
Stack snippet
/* for demo purpose */
body { margin: 0; }
.flex-container { height: 100vh; }
.grid-x { border: 1px solid red; }
.small-6 { border: 1px solid blue; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.css" rel="stylesheet"/>
<div class="flex-container">
<div class="flex-child-grow grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>

Understanding how Flexbox works with Bootstrap

I have the following HTML and CSS layout:
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 100px;
}
.col-md-6 {
display: flex;
justify-content: center;
}
.container_flex {
display: flex;
align-items: center;
justify-content: center;
/* vh refers to viewport height. Very useful! */
height: 100vh;
width: 100%;
}
<div class="container-fluid">
<div class="container_flex">
<div class="row">
<div class="col-md-6 col-xs-12" style="border:solid">
<h1>Column 1</h1>
</div>
<div class="col-md-6 col-xs-12" style="border:solid">
<h1>Column 2</h1>
</div>
</div>
</div>
</div>
Which provides the following result:
Bootply
My aim of using Flexbox is to vertically center the contents of "row" inside the container-fluid. However, this results in the columns adopting a compressed look when in desktop mode. When in mobile view, the columns do stack as expected. I would be grateful if someone could explain why this compressed/stubby look comes about?
In contrast, if I remove the row class, this stubby compressed look no longer is brought about as shown:
Bootply
However, the columns no longer stack when in mobile view. Is there any way that I can rectify this?
If anyone has any tips/pointers on how to effectively use FlexBox with Bootstrap to vertically and horizontally center in a more effective way than what I have attempted here, I would be very grateful.
When you remove the row element the .col elements become your flex-items. In order to get flex-items to wrap in a flex container you need to use the flex-wrap property. However, I don't think removing the row element and using flex-wrap is what you really want.
With regards to your question. The reason it looks stubby in your first example is because you are making the row element your 'flex-item'. The width of the row item then sizes to its contents because you have not set the flex property which controls its size. Once you set the flex property properly then you will see the desired results:
.container_flex {
display: flex;
align-items: center;
justify-content:center;
/* vh refers to viewport height. Very useful! */
height: 100vh;
width: 100%;
}
.row {
flex: 1;
}
<div class="container-fluid">
<div class="container_flex">
<!-- Note that if using Flexbox, then do not need to wrap col- in row class but then does not stack columns on mobile... use #media? -->
<div class="row">
<div class="col-md-6 col-xs-12" style="border:solid">
<h1>Column 1</h1>
</div>
<div class="col-md-6 col-xs-12" style="border:solid">
<h1>Column 2</h1>
</div>
</div>
</div>
</div>
Here is a brief explanation why: flex:1 is a shortcut property that sets three separate flex-item properties to:
flex-grow: 1; If the size of the flex-item is smaller than available space within the flex container then setting this to a value greater than 0 makes the item stretch to fill the available space. If there are multiple flex-items in the same container they grow to share the available space in proportion to the value of their flex-grow property.
flex-shrink: 1; If the size of the flex-item is larger than the available space within the flex container then setting this to a value greater than 0 makes the item shrink to fit the available space. If there are multiple flex-items in the same container they will shrink to share the available space in proportion to the value of their flex-shrink property.
flex-basis: 0%; Defines the starting size of the element before being "flexed".
For general informanton on using flex-box take a look at this article over at css tricks by Chris Coyier; he does a great job explaining how flex-box works.
If you are looking for information on using bootstrap and flex-box together I recommend reading this article as well!
I hope this helps.
you need to give flex:1 to .row which it shorthand for flex-grow, flex-shrink and flex-basis combined. Default is 0 1 auto, using flex:1 means it will be 1 1 0
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 100px;
}
.row {
flex: 1
}
.col-md-6 {
display: flex;
justify-content: center;
}
.container_flex {
display: flex;
align-items: center;
justify-content: center;
/* vh refers to viewport height. Very useful! */
height: 100vh;
width: 100%;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container-fluid">
<div class="container_flex">
<div class="row">
<div class="col-md-6 col-xs-12" style="border:solid">
<h1>Column 1</h1>
</div>
<div class="col-md-6 col-xs-12" style="border:solid">
<h1>Column 2</h1>
</div>
</div>
</div>
</div>
You may also use the flex built-in library from bootsrap (it will also be responsive):
http://v4-alpha.getbootstrap.com/layout/flexbox-grid/#responsive-flexbox
.col-md-6.col-xs-12{border:solid}/* CSS neede cause border are not set by default in bootsrap :) */
<link href="http://v4-alpha.getbootstrap.com/assets/css/docs-flexbox.min.css" rel="stylesheet"/>
<link href="http://v4-alpha.getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<p>To see cols side by side, run snippet in full page mode and reduce it down to average 720px width to see col stacking </p>
<div class="row">
<div class="col-md-6 col-xs-12" >
col 1
</div>
<div class="col-md-6 col-xs-12" >
col 2
</div>
</div>
</div>

How to create a 3 column layout in css?

I have been trying to make a complex UI for my program and I wanted to be able to have 3 columns using css in my design.
This is currently my code:
<div style="width:100px;">stuff</div>
<div style="width:100px;">stuff</div>
<div style="width:100px;">stuff</div>
But this, for some reason, will display 3 different lines of stuff.
I have tried to change some things but it didn't seem to work at all
I just want there to be 3 columns on the same block.
If you want to have 3 differnet areas on the screen, the effective method for doing that would be:
<style> .third { width: 33.33%; float: left; } </style>
<div class="third"> Something </div>
<div class="third"> Something </div>
<div class="third"> Something </div>
The class="third" is adding the css that is inside of the {}'s that I have made. - Meaning that each of the div's are given the width: 33.33% (1/3 of the screen) and a float: left which will just move the areas to be able to move out of the normal CSS and HTML scope of stacking on top of each other.
Hope this helps! :)
There are a couple ways to accomplish what you want.
Method 1: Float and width
Assign a single column class
.column {
width: 33.3%;
float: left;
}
Markup three divs with said class
<div class="column">Column 1</div>
<div class="column">Column 2</div>
<div class="column">Column 3</div>
Method 2: Inline block
Sometimes floats aren't the best option. You cna also set the display property to inline-block, although this can sometimes leave unwanted gaps in between the divs.
.column {
width: 33.3%;
display: inline-block;
}
Same HTML markup
<div class="column">Column 1</div>
<div class="column">Column 2</div>
<div class="column">Column 3</div>
Method 3: Flexbox
Flexbox according to Chris Coyier of CSS-tricks:
The Flexbox Layout (Flexible Box) module (currently a W3C Last Call Working Draft) aims at providing a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word "flex").
.row {
display: -ms-flex: // Vendor prefixes required for flexbox
display: -webkit-flex;
display: flex:
}
.column {
width: 100px;
display: -ms-inline-flex;
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}
Add the parent div to your HTML markup
<div class="row">
<div class="column">Column 1</div>
<div class="column">Column 2</div>
<div class="column">Column 3</div>
</div>
Cool thing about flexbox is you don't need to fill the space using set percentages, it can space your columns out with justify-content: space-between;
There is a lot more to delve into with flexbox. Floats are very simple but since you mentioned building a UI, something like flexbox will give you a wider array of tools to work with.
Alternatively, you could style them all at once without giving a class as mentioned by Jek. If you are using styling within the html, you could do this in the header:
<style>
div{
width:100px
}
</style>
You could do the same if you are using an external stylesheet. However, if you have to style the divs in different manners using class and id would be a better option. If all divs are styled in the same way, simply style the tag, which is div in your case.

CSS: Keep Aspect Ratio of an Element for Given Height

The above link to a possible duplicate is not a solution for this case, because the height will be a fixed value for several breakpoints.
I have some DIVs with display:inline-block, so they are floating nicely side by side. These DIVs all have the same height, e.g. height:300px. Later, I will load an image inside every DIV with Ajax, and I want the DIV to keep the aspect ratio of the image, so they won't wiggle all around, when the image is actually loaded.
So when the DIVs are displayed in the browser, the images are not yet there, so fixing the height for the image with height:auto; won't work.
Sample code:
<div class="wrapper">
<div class="item">...</div>
<div class="item">...</div>
<!-- More items here -->
</div>
CSS:
.item {
display:inline-block;
vertical-align:top;
height: 300px;
width: /* depending on the image ratio */
}
Now I know how to keep the aspect ratio of an element for a given width (see here or here). But since my DIVs should all have the same height, how can I keep the aspect ratio and change just the width?
One (not really good) solution would be to insert a blank image and to resize this image to the right dimensions.
The problem is: when resizing the window, the height of all the DIVs will change, so just calculating the width is not enough. I could recalculate the width with Javascript, but I prefer a plain CSS version (if possible).
So here is my question: how can I keep the aspect ratio for an element for a given height by CSS only?
Thanks
You have the aspect ratio but not actual image dimensions. I think you can use the calc function for this. Browser support is an issue though:
/* Note: using 30px height for demonstration */
.item {
display: inline-block;
vertical-align: top;
height: 30px;
background: #FC0;
}
.ratio-3-2 .item {
/* 3:2 = 1.5 */
width: calc(30px * 1.5);
}
.ratio-4-3 .item {
/* 4:3 = 1.3333 */
width: calc(30px * 1.3333);
}
<div class="wrapper ratio-3-2">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="wrapper ratio-4-3">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
In the above demo, the first set of divs will be 45px wide and the second set will be 40px wide.
I would set the width of the DIV according to template I'm using, so it would be responsive, and add this to my code:
img.item {
width:auto; height:300px;width: auto\9; // for IE
}
This will make sure you could control the DIV while the images would fit there nicely
Mind due you may want to change it to max-height:300px; for responsive site