How to make inner div full height with unknown height parent? - html

I need .col to be 100% of .row height but you can see that the second .col falls short. How can I get this to work without using any "magic numbers"?
http://jsfiddle.net/b21g6fme/
.row {
position: relative;
background: #f99;
}
.col {
margin: 0 0 0 8px;
display: inline-block;
width: 40%;
position: relative;
vertical-align: top;
background: #999;
height: 100%;
}
.col:first-child {
margin: 0;
}
.item {
display: block;
position: relative;
top: 0;
margin: 12px 0 0 0;
min-height: 80px;
width: 100%;
outline: 4px solid black;
}
.item:first-child {
margin: 0;
}
.item.large {
min-height: 120px;
height: 100%;
}
.item.red {
background: #f00;
}
.item.blue {
background: #0f0;
}
.item.green {
background: #00f;
}
<div class="row">
<div class="col">
<div class="item red"></div>
<div class="item blue"></div>
</div>
<div class="col">
<div class="large item green"></div>
</div>
</div>

This can be achieved by using flexbox:
Add display: flex; to .row. This tells its children to use the flexbox model
Add flex-direction: row; to .row as we want the children to align horizontally
Add display: flex; to .col. This tells its children to use the flexbox model
Add flex-direction: column; to .col as we want the children to align vertically
Add flex: 1; to .item to allow it to grow and fill the available space if required
A number of styles can be removed from your original version as they are no longer required when using flexbox
.row {
background:#f99;
display: flex;
flex-direction: row;
}
.col {
background: #999;
display: flex;
flex-direction: column;
margin:0 0 0 12px;
width:40%;
}
.col:first-child {
margin:0;
}
.item {
flex: 1;
margin: 12px 0 0 0;
min-height: 80px;
outline:4px solid black;
width: 100%;
}
.item:first-child {
margin:0;
}
.item.red {
background:#f00;
}
.item.blue {
background:#0f0;
}
.item.green {
background:#00f;
}
<div class="row">
<div class="col">
<div class="item red"></div>
<div class="item blue"></div>
</div>
<div class="col">
<div class="large item green"></div>
</div>
</div>
flexbox support is pretty good, although it isn't supported by older versions of IE. http://caniuse.com/#feat=flexbox

You can do it via flexbox if you don't care about any IE below 11.
I showed how it can be done here.
.row {
position: relative;
background:#f99;
display: flex;
}
.col {
margin:0 0 0 8px;
display:inline-block;
width:40%;
position: relative;
vertical-align:top;
background: #999;
}
.col:first-child {
margin:0;
}
.col:last-child {
display:flex;
}
.item {
display:block;
position: relative;
top:0;
margin: 12px 0 0 0;
min-height: 80px;
width: 100%;
outline:4px solid black;
}
.item:first-child {
margin:0;
}
.item.large {
min-height:120px;
}
.item.red {
background:#f00;
}
.item.blue {
background:#0f0;
}
.item.green {
background:#00f;
}

Here is the simplified CSS table layout, the trick is set the full height div to absolute position with top and bottom both set to 0.
JsFiddle Demo
.row {
display: table;
}
.col {
display: table-cell;
vertical-align: top;
position: relative;
}
.item.large {
position: absolute;
top: 0;
bottom: 0;
}
.item.red {
background: red;
}
.item.blue {
background: blue;
}
.item.green {
background: green;
}
<div class="row">
<div class="col">
<div class="item red">r<br/>e<br/>d</div>
<div class="item blue">blue</div>
</div>
<div class="col">
<div class="large item green">green</div>
</div>
</div>

Children item height in percentage value will only work if parent item have height defined.
Otherwise you can achieve it with jQuery
$(".col").height($(".row").height());

Try out this
.large.item {
height:100%;
}

If you can make the parent relative positioned, and the child absolute possitioned, giving the child a value of 0 for top an bottom will make it stretch to the parents full height.

Related

Make content scroll horizontally within nested flex containers with position sticky

I have the following layout (see snippet below).
This is the expected behavior.
The problem is:
Once the extra-large-content is simulated (by removing the comment on the extra-large-content CSS rule), it breaks the layout.
I would like the extra-large-content to scroll horizontally while staying inside column-3.
Is this even possible?
(the code is also available here https://codepen.io/Ploddy/pen/NWXOgMG?editors=1100)
body {
height: 1920px;
margin: 0;
}
.container {
display: flex;
border: 1px solid #ccc;
margin: 1rem;
}
.container > * {
border: 1px solid #ccc;
position: sticky;
top: 0;
align-self: flex-start;
flex-grow: 1;
margin: 1rem;
}
#column-3 {
height: 300px;
}
#extra-large-content {
background-color: lightgreen;
/*width: 3000px;*/
}
<div class="container">
<div>
column-1
</div>
<div class="container">
<div>
column-2
</div>
<div id="column-3">
column-3
<div id="extra-large-content">
extra-large content
</div>
</div>
</div>
</div>
This should work nicely for you. Essentially, I just specified width's on the .container elements. In theory, you could put overflow-x: scroll; on the .container, however, this would break your sticky positioning.
Edit ~ OP wants the extra-large content to scroll horizontally, not the entire column-3.
Set overflow-x: scroll; on the new parent wrapper of the div that has the 3000px static width.
body {
height: 1920px;
margin: 0;
}
.container:first-child {
max-width: 100%;
}
.container:first-child > div:first-child {
width: 40%;
}
.container:nth-child(2) {
width: 60%;
}
.container:nth-child(2) > div:first-child {
margin: 1em 0em 1em 1em;
}
.container {
display: flex;
border: 1px solid #ccc;
margin: 1rem;
}
.container>* {
border: 1px solid #ccc;
position: sticky;
top: 0;
align-self: flex-start;
flex-grow: 1;
margin: 1rem;
}
.wrapper {
display: flex;
flex-direction: column;
width: 40%;
}
#column-3 {
background-color: salmon;
}
#extra-large-content {
height: 300px;
width: 3000px;
background-color: lightgreen;
}
.xl-content-wrapper {
overflow-x: scroll;
}
<div class="container">
<div>column-1</div>
<div class="container">
<div>column-2</div>
<div class="wrapper">
<div id="column-3">column-3</div>
<div class="xl-content-wrapper">
<div id="extra-large-content">extra-large content</div>
</div>
</div>
</div>
</div>
The issue comes from using flexbox.
Switching to grid fixes the problem.
body {
height: 1920px;
margin: 0;
}
#primary-container {
position: relative;
display: flex;
margin: 1rem;
}
#secondary-container {
position: relative;
display: grid;
grid-template-columns: max-content 1fr;
align-items: start;
}
#column-3 {
display: grid;
grid-auto-rows: min-content;
height: 200px;
}
#content-wrapper {
overflow: auto;
}
#extra-large-content {
width: 3000px;
background-color: lightgreen;
}
.sticky {
position: sticky;
top: 0;
align-self: flex-start;
}
.border {
border: 1px solid #ccc;
}
<div id="primary-container" class="border">
<div class="sticky">
column1
</div>
<div id="secondary-container" class="border">
<div class="sticky">
column2
</div>
<div id="column-3" class="sticky border">
column3
<div id="content-wrapper">
<div id="extra-large-content">
extra-large content
</div>
</div>
...
</div>
</div>
</div>

Add responsive image to a website split into 4 responsive boxes

I want to make a website that would consist of 4 boxes each 50% height and width. I found code that does that, but now I struggle to add images into each box. I want each of the four divs to have a different image, and they should scale according to window size. Any help is appreciated.
Here's my codepen: https://codepen.io/alanvkarlik/pen/OJRdyRR
Here's what I would like to achieve: https://i.imgur.com/7CR7sW8.jpg
HTML:
<div class="container">
<div class="column"><img src="https://f4.bcbits.com/img/a0846297992_16.jpg"></div>
<div class="column">IMG 2</div>
<div class="column">IMG 3</div>
<div class="column">IMG 4</div>
</div>
CSS:
html, body {
height: 100%;
margin: 0;
}
.container {
height: 100%;
}
.column {
height: 25%;
display: flex;
justify-content: center;
align-items: center;
}
#media screen and (min-width: 600px) {
.container {
display: flex;
flex-wrap: wrap;
}
.column {
flex-basis: 50%;
height: 50%;
}
}
/* general styles */
body {
font-family: 'Lato', sans-serif;
font-size: 1.3em;
color: #ccc;
background: #000;
/*margin-bottom: 70px;*/
}
.column {
padding: 15px;
/*border: 1px solid #666;*/
box-sizing: border-box;
}
.column:nth-child(1) {
background: #5c9;
}
.column:nth-child(2) {
background: #fb0;
}
.column:nth-child(3) {
background: #39f;
}
.column:nth-child(4) {
background: #f33;
}
main {
max-width: 1200px;
margin: 0 auto;
}
h1,
h2 {
text-align: center;
}
Not sure if this is what you're trying to achieve but I'd do it with by setting object-fit: contain on images. I also changed a bit the way (css) you're defining the divs.
body {
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
}
.column {
height: 50vh;
width: 50vw;
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
box-sizing: border-box;
}
.column img {
height: 100%;
width: 100%;
object-fit: contain;
}
.column:nth-child(1) {
background: #5c9;
}
.column:nth-child(2) {
background: #fb0;
}
.column:nth-child(3) {
background: #39f;
}
.column:nth-child(4) {
background: #f33;
}
<div class="container">
<div class="column"><img src="https://f4.bcbits.com/img/a0846297992_16.jpg"></div>
<div class="column">IMG 2</div>
<div class="column">IMG 3</div>
<div class="column">IMG 4</div>
</div>
I think this is what you are looking for.
Your column img class is set to 100% width and height. I set the height to 50% and the width to auto so it detects the image size and displays it noramlly.
And i simply removed the "object-fit: cover;".
If you change your .colum img {} to the following it should be exactly what you want.
.column img {
height: 50%;
width: auto;
}
I added a snippet so you can see it working.
body {
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
}
.column {
height: 50vh;
width: 50vw;
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
box-sizing: border-box;
}
.column img {
height: 50%;
width: auto;
}
.column:nth-child(1) {
background: #5c9;
}
.column:nth-child(2) {
background: #fb0;
}
.column:nth-child(3) {
background: #39f;
}
.column:nth-child(4) {
background: #f33;
}
<div class="container">
<div class="column"><img src="https://f4.bcbits.com/img/a0846297992_16.jpg"></div>
<div class="column">IMG 2</div>
<div class="column">IMG 3</div>
<div class="column">IMG 4</div>
</div>

Prevent element from overflowing container

I have the following structure, where the number of names (.name) in .list is dynamic. What i would like to achieve is when content (depending on n of .names) is longer than .parent's fixed height, both .children fit inside the .parent (inherit height). Lack of space would be solved with .list getting a scrollbar (overflow:auto).
Height inheritance works well with single child, but I am having huge problems when there are two or more.
JSFIDDLE HERE
HTML
<div id="grandparent">
<div id="parent">
<div id="list" class="children">
<div class="name">john</div>
<div class="name">mike</div>
<div class="name">jack</div>
<div class="name">terry</div>
</div>
<div id="footer" class="children">
<div>footer</div>
</div>
</div>
</div>
CSS
body, html {
margin: 0;
width: 100%;
height: 100%;
}
div {
box-sizing: border-box;
}
#grandparent {
background-color:yellow;
display:flex;
align-items:center;
width:100%;
height: 100%;
flex: 1;
}
.children, .children div {
padding: 5px;
}
.children {
max-height: inherit;
}
.children div {
width: 100%;
max-height: inherit;
}
#list {
overflow: auto;
padding-bottom:0;
}
#footer {
padding-top:0;
}
.name {
background-color: green;
}
#footer div {
background-color: pink;
}
#parent {
background-color: blue;
margin: 0 auto;
max-height: 100px;
}
P.S. sorry for the code mess, i was just testing out different options.
Add this to your code:
#parent {
display: flex;
flex-direction: column;
}
body,
html {
margin: 0;
width: 100%;
height: 100%;
}
div {
box-sizing: border-box;
}
#grandparent {
background-color: yellow;
display: flex;
align-items: center;
width: 100%;
height: 100%;
flex: 1;
}
.children,
.children div {
padding: 5px;
}
.children {
max-height: inherit;
}
.children div {
width: 100%;
max-height: inherit;
}
#list {
overflow: auto;
padding-bottom: 0;
}
#footer {
padding-top: 0;
}
.name {
background-color: green;
}
#footer div {
background-color: pink;
}
#parent {
background-color: blue;
margin: 0 auto;
max-height: 100px;
/* new */
display: flex;
flex-direction: column;
}
<div id="grandparent">
<div id="parent">
<div id="list" class="children">
<div class="name">john</div>
<div class="name">mike</div>
<div class="name">jack</div>
<div class="name">terry</div>
</div>
<div id="footer" class="children">
<div>footer</div>
</div>
</div>
</div>
jsFiddle demo
Because flex items are set to flex-shrink: 1 by default, they will reduce their size in order to not overflow the container.

Flexbox element height 100% going outside of parent?

So because of design reasons I had to use flexbox here and I needed the btn p elements to act like display block, which I managed to through another stack post, but now when I make the "other divs" class 100%, it goes out of the main parent, I cannot figure out why?
#outterWrapper {
display: inline-block;
height: 200px;
border: 1px solid red;
}
#container {
display: flex;
height: 200px;
flex-wrap: wrap;
}
#menu {
display: flex;
flex-basis: 100%;
}
#menu p {
margin: 0;
padding: 8px;
padding-bottom: 0;
}
.otherDivs {
height: 100%;
width: 25%;
background-color: grey;
margin-right: 5px;
}
<div id="outterWrapper">
<div id="container">
<div id="menu">
<p>Btn</p>
<p>Btn</p>
<p>Btn</p>
</div>
<div class="otherDivs"></div>
</div>
</div>
As from the example above the grey box goes outside of the red border?
You can switch to column direction and have something like this :
#outterWrapper {
display: inline-block;
height: 200px;
border: 1px solid red;
}
#container {
display: flex;
height: 200px;
flex-direction:column;
}
#menu {
display: flex;
}
#menu p {
margin: 0;
padding: 8px;
padding-bottom: 0;
}
.otherDivs {
height: 100%;
width: 25%;
background-color: grey;
margin-right: 5px;
}
<div id="outterWrapper">
<div id="container">
<div id="menu">
<p>Btn</p>
<p>Btn</p>
<p>Btn</p>
</div>
<div class="otherDivs"></div>
</div>
</div>

Website image spacing correctly

I want my images next to each other with a little margin in between. But when I do `margin-right: 10px; on each div the last image wont align with my title bar.
How can I give the divs a space in between without having a space on the right of the last div?
Note: The content is dynamic, so I cant make a div to hold the 4 divs.
There are many ways you can do, I'll just show one of them.
EDIT 1: solution for multiple rows by using nth-child
DEMO: http://jsfiddle.net/s0xLfcrx/1/
HTML:
<div class="bar"></div>
<div class="box">
<div>a</div>
<div>b</div>
<div>c</div>
<div>d</div>
<div>e</div>
<div>f</div>
<div>g</div>
<div>h</div>
</div>
CSS:
.bar, .box {
width: 460px;
}
.bar {
background: lime;
height: 20px;
}
.box {
text-align: center;
font-size: 0;
}
.box > div {
display: inline-block;
font-size: 16px;
background: gold;
width: 100px;
margin: 0 10px;
}
.box > div:nth-child(4n+1) {
margin-left: 0;
}
.box > div:nth-child(4n) {
margin-right: 0;
}
ORIGINAL DEMO (for only 1 row):
http://jsfiddle.net/s0xLfcrx/
You could use justify-content: space-between. This creates even spacing inbetween each of the image containers and pushes the first and last element to the edges of the parent div.
Your html:
.container {
width: 346px;
}
.title-bar {
background-color: #ccc;
width: 100%;
}
.flex-container {
padding: 0;
margin: 0;
list-style: none;
-ms-box-orient: horizontal;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
}
.space-between {
-webkit-justify-content: space-between;
justify-content: space-between;
}
.image-container {
background: #ccc;
padding: 5px;
width: 60px;
height: 50px;
margin: 0;
line-height: 50px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}
<div class="container">
<div class="title-bar">
<h1>Title</h1>
</div>
<div class="flex-container space-between">
<div class="image-container">1</div>
<div class="image-container">2</div>
<div class="image-container">3</div>
<div class="image-container">4</div>
</div>
</div>
The styling for the image-containers in the code above is just an example - if you have an unknown number of divs loading you either fix the width, or make them fluid and the container width will need to be fluid (unless you want it fixed of course).
you could do something like this with variable widths:
.titlebar {
width: calc(100% - 2px);
display: block;
height: 40px;
background: blue;
}
.item25 {
width: calc(25% - 11px);
height: 80px;
display: inline-block;
background: black;
margin-right: 10px;
}
.no-margin {
margin-right: 0;
}
<div class="titlebar"></div>
<div class="item25"></div>
<div class="item25"></div>
<div class="item25"></div>
<div class="item25 no-margin"></div>
Just use simple CSS
.div { width: 25%; text-align: center; padding: 5px; box-sizing: border-box; }
.div img { display: block; margin: 0 auto; }
There are many ways to do but if you need RESPONSIVE for this then use this solution:
body{font-family:arial;}
h1{
display:block;
margin:0px;
padding:0px;
background:#0af;
color:#fff;
text-align:center;
}
.layer{
display:block;
overflow:auto;
}
.layer > div{
display:block;
float:left;
margin:10px 10px 10px 0px;
width: -moz-calc(25% - 7.5px);
width: -webkit-calc(25% - 7.5px);
width: calc(25% - 7.5px);
background-color:#000;
height:30px;
}
.layer > div:nth-child(4n) {
margin-right: 0;
background-color:#f00;
}
<h1>Title bar</h1>
<div class="layer">
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div><div></div>
</div>