CSS: General way to make an element fill its container? - css

How can we make a margin element fill a flexbox item that is not itself a flexbox?
An element (even a nested one with margins) can easily fill its container using position: absolute -- if it's not inside a flexbox item. Why does this not work for an element inside a flexbox item?
<main>
<nav>NAV</nav>
<section>
<div>DIV</div>
</section>
</main>
<style>
html, body {
position:absolute; top:0; left:0; right:0; bottom:0;
margin: 0;
}
main {
position:absolute; top:0; left:0; right:0; bottom:0;
display: flex;
}
nav {
flex-basis: 250px;
background-color: #eee;
}
section {
flex-basis: 100%;
background-color: #ccc;
margin: 10px;
}
div {
/* position:absolute; top:0; left:0; right:0; bottom:0; */
/* why doesn't the above line work? */
background-color: #cfc;
margin: 10px;
}
</style>
There are many similar-looking questions like this one and this one that don't really apply to items inside flexboxes or items with margin. There are loads of special-case solutions like align-self: stretch, height: 100% and box-sizing: border-box that just don't work in this example because of the nested margin or the fact that the flexboxes themselves aren't nested. The problems with these one-off hacks go on and on...
So what is the general method to fill a flexbox item? What is the issue with position:absolute here? What is the most general way to make an element fill its container?

<main>
<nav>NAV</nav>
<section>
<div>DIV</div>
</section>
</main>
<style>
html, body {
position:absolute; top:0; left:0; right:0; bottom:0;
margin: 0;
min-height: 100%;
}
main {
position:absolute; top:0; left:0; right:0; bottom:0;
display: flex;
min-height: 100%;
}
nav {
flex-basis: 250px;
background-color: #eee;
}
section {
flex-basis: 100%;
background-color: #ccc;
margin: 10px;
display: flex;
}
div {
/* position:absolute; top:0; left:0; right:0; bottom:0; */
/* why doesn't the above line work? */
background-color: #cfc;
margin: 10px;
flex: 1;
}
</style>

Below is an idea you might find worth exploring? I put the nav as a sibling of main rather than a child. That's not necessary for the CSS but the structure makes most sense. Ideally, you have header, nav``main,footer, possibly an aside as well. You really want to avoid all that absolute positioning. It does not play well on mobile phone - imagine what happens if you put a textbox or textarea on your page and a mobile user clicks on it and the soft-keyboard pops up.
body {
display: grid;
grid-template-columns: [left] 196px [main] 1fr [right];
grid-template-rows: [top] 1fr [bottom];
grid-gap: 4px;
outline: 1px dashed #616161;
min-height: 100vh;
min-width: 0;
}
body > nav {
outline: 1px dashed red;
grid-column-start: left;
grid-column-end: main;
grid-row-start: top;
grid-row-end: bottom;
}
body > main {
outline: 1px dashed blue;
grid-column-start: main;
grid-column-end: right;
grid-row-start: top;
grid-row-end: bottom;
display: flex;
flex-flow: column nowrap;
}
section {
flex: 1 1 auto;
display: flex;
flex-flow: column nowrap;
}
div {
flex: 1 1 auto;
margin: 4px;
outline: 1px dotted green;
min-height: auto;
}
<nav>NAV</nav>
<main>
<section>
<div>DIV</div>
</section>
</main>

Related

How to connect two divs with a line responsively?

I am using a flexbox to create a sort of pill navigation/wizard system like this:
.wizard-container {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
.pill {
background: orange;
padding: 3px 15px;
color: white;
margin: 0;
display: inline-block;
border-radius: 10px;
}
.connector {
display: inline-block;
background: orange;
height: 7px;
flex-grow: 1;
}
<div class="wizard-container">
<div class="pill">Hello</div>
<div class="connector"></div>
<div class="pill">Beautiful</div>
<div class="connector"></div>
<div class="pill">World</div>
</div>
As you may be able to see, the flexbox wraps the .pill elements vertically when the viewport is reduced, but the .connector elements remain horizontal and frankly look quite ugly. I could write a media query to display: none them out, but I was wondering if it's possible to sort of have them draw a sort of snake path starting from the right side of the pill above and ending by the left of the pill below?
I would do this differently using pseudo element and the connector will disappear when the element will wrap. You can have a vertical ones as a bonus to keep the linking.
.wizard-container {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
overflow:hidden; /* This one is important */
}
.pill {
background: orange;
padding: 3px 15px;
color: white;
border-radius: 10px;
font-size:25px;
position:relative;
margin:0 0 10px;
}
.pill:before {
content:"";
position:absolute;
z-index:-1;
right:100%;
height:7px;
top:50%;
transform:translateY(-50%);
width:100vw;
background:inherit;
}
.pill:after {
content:"";
position:absolute;
z-index:-1;
bottom:100%;
width:7px;
left:40px;
height:100vh;
background:inherit;
}
<div class="wizard-container">
<div class="pill">Hello</div>
<div class="pill">Beautiful</div>
<div class="pill">World</div>
</div>

CSS Position Div Over Another Div

I have two divs that I am trying to stack over each other but the one I want on top is not showing. I want the blue background div to lay on top of the red background div. Any advice? The reason why I want to overlay the blue div is because the container is a centered grid and I want the red div to be the background for the first half of the page.
JSFIDDLE
CSS
.buddy {
width: 50%;
height: 629px;
display: inline-block;
position: relative;
background: red;
}
.buddy-content {
position: absolute;
top: -629px;
z-index: 10;
background: blue;
}
.container {
max-width: 1000px;
margin: 0 auto;
overflow:hidden;
position:relative;
padding: 0 10px;}
You have made the second div absolute so you don't need to give the negative value for top. The second div is hiding because you top -629px; Try making the top:0 and see. And also for your current code. Remove the overflow hidden and put z-index like this:
.buddy {
width: 50%;
height: 629px;
display: inline-block;
position: relative;
z-index:9;
background: red;
}
.buddy-content {
position: absolute;
top: -629px;
z-index: 10;
background: blue;
}
.container {
max-width: 1000px;
margin: 0 auto;
width:200px;
height:200px;
position:relative;
padding: 0 10px;
}
.buddy {
width: 50%;
height: 629px;
display: inline-block;
position: absolute;
background: red;
}
.buddy-content {
position: absolute;
z-index: 10;
background: blue;
}
<div class="buddy BlueGradient">
</div>
<div class="container">
<div class="buddy-content">
ROGER
</div>
</div>
https://jsfiddle.net/kt77cp3e/6/
just add z-index : higher to the div that you want to show on top and set z-index low to the other one ..
ant one thing your code is working good just you need to remove " top : -629px;"
that thing is not allowing blue div to be on top just it is showing at the -629 px position..!!!!
If you can update your code like this, it may solve the issue:
Demo:https://jsfiddle.net/kt77cp3e/7/
CSS:
html, body {
height:100%;
width:100%:
}
.container {
width:50%;
height:100%;
background:red;
position:relative;
}
.container>div {
position:relative;
left:0;
right:0;
}
.container>div:first-child {
top:0;
height:50%;
background:blue
}
.container>div:last-child {
bottom:0;
height:50%;
background:green
}
HTML:
<div class="container">
<div></div>
<div></div>
</div>
Update: Considering the latest updated code, I think you should remove overflow:hidden from the container styles. That should do the trick
You should set the dimension on the .container div.
CSS:
.container {
position:relative;
width:100px; //You may modify these values
height:100px
}
Demo: https://jsfiddle.net/kt77cp3e/1/
.buddy { width: 50%; height: 629px; display: inline-block; position: relative; background: red;}
.buddy-content { position: absolute; top: 0px; z-index: 10; background: blue; }
.container {max-width: 1000px; margin: 0 auto; overflow:hidden; position:relative; padding: 0 10px; position: relative;}
<div class="container">
<div class="buddy BlueGradient">
<div class="buddy-content">ROGER</div>
</div>
</div>
This brings the text "Roger" with blue background on top of the red background

Flex css layout with fixed and variable elements

I am hoping to create the following layout in pure CSS. I know that I can achieve this with a JavaScript solution, but a CSS solution would be much cleaner, if it is possible.
I have created a jsFiddle which I know is incorrect, to provide a starting point. The HTML and CSS I use in the jsFiddle are shown below.
Notes:
I would like this to fill the full height of the window, so that there is no scroll bar for the page (but see my last point)
There are two sections that can contain a variable number of elements.
The red elements are images which the user can add on the fly, and which will be given a frame with a fixed aspect ratio (shown here as a square)
The green section will contain a list which will have at least one item, so it will have a fixed minimum height. It may have up to four items, so its height may change. I would prefer not to have this section scroll. If the user makes the window too short for both the green and the blue elements to show full height, then the page as a whole will have to scroll.
My question is: can this be done in pure CSS? If you know that there is a solution, and if you can provide some pointers as to how I can achieve it, then I can continue to work towards that solution. If you know that there is no solution, then I will simply adopt a JavaScript approach.
If there is a solution, and you would be happy to share it, then I will be delighted that you have saved me a lot of time.
<!DOCTYPE html>
<html>
<head>
<title>Flex</title>
<style>
body, html {
height: 100%;
margin: 0;
background: #000;
}
main {
width: 30em;
height: 100%;
margin: 0 auto;
background: #333;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.head{
width:100%;
-webkit-flex: 3em;
flex: 3em;
background: #fcc;
}
.expand{
width:100%;
overflow:auto;
}
.filler {
width:100%;
height:20em;
background: #003;
border-bottom: 1px solid #fff;
}
.space {
width:100%;
height:10em;
border-bottom: 1px solid #fff;
}
.foot{
width:100%;
-webkit-flex: 0 0 2em;
flex: 0 0 2em;
background: #cfc;
}
</style>
</head>
<body>
<main>
<div class="head">HEAD</div>
<div class="expand">
<div class="space"></div>
<div class="filler"></div>
<div class="space"></div>
</div>
<div class="foot">FOOT</div>
</main>
</body>
</html>
If I understand it well,
main {
height: auto;
min-height: 100%;
}
.head {
min-height: 3em;
}
.foot {
min-height: 2em;
}
.expand {
flex-basis: 0; /* Initial height */
flex-grow: 1; /* Grow as much as possible */
overflow: auto;
}
body,
html {
height: 100%;
margin: 0;
background: #000;
}
main {
width: 20em;
min-height: 100%;
margin: 0 auto;
background: #333;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.head {
width: 100%;
min-height: 3em;
background: #fcc;
}
.expand {
width: 100%;
flex-basis: 0;
flex-grow: 1;
overflow: auto;
}
.filler {
width: 100%;
height: 20em;
background: #003;
border-bottom: 1px solid #fff;
}
.space {
width: 100%;
height: 2em;
border-bottom: 1px solid #fff;
}
.foot {
width: 100%;
min-height: 2em;
background: #cfc;
}
<main>
<div class="head">HEAD</div>
<div class="expand">
<div class="space"></div>
<div class="filler"></div>
<div class="space"></div>
</div>
<div class="foot">FOOT</div>
</main>

How to center an image inside a div in the exact middle

I am trying to center an image inside a div in the exact middle - horizontally and vertically, but this is not working for me:
#col_as_table
{
float:left;
position:relative;
width:14%;
min-height:100px;
height:auto;
display: table;
display: table-cell;
text-align: center;
vertical-align: middle;
}
HTML
<div id="col_as_table"><img src="test.png"></div>
Give this a shot. You'll need an extra div.
Fiddle!
HTML:
<div class="divTable">
<div class="innerDivTable">
<img src="test.png"/>
</div>
</div>
CSS:
.divTable {
width: 200px; /* purely for demonstration */
height: 200px; /* purely for demonstration */
display: table;
border: 1px solid black;
}
.innerDivTable {
display: table-cell;
vertical-align: middle;
text-align: center;
}
Fiddle: http://jsfiddle.net/4mYj3/1/
CSS:
#col_as_table
{
position:relative;
margin: auto;
text-align: center;
vertical-align: middle;
display: table;
height:500px;
}
img{
position: absolute;
top: 50%;
left: 0;
bottom: 0;
right: 0;
}
I wrote a Pen some time ago for the same purpose. It shows 3 methods on how you can center an image vertically as well as horizontally.
I'd personally use absolute positioning or table cell depending upon the situation.
#div3{
display:table-cell;
vertical-align:middle;
}
#div1 img{
height:100px;
position:absolute;
top:50%;
left:50%;
-webkit-transform:translateY(-50%) translateX(-50%);
}
Here's a fiddle:
http://jsfiddle.net/C4DC7/
There are many ways to accomplish this. My example expands on the idea that you can afford your images to expand the parent div element.

Button at the center and bottom of div

How to make a button be at the bottom of div and at the center of it at the same time?
.Center {
width: 200px;
height: 200px;
background: #0088cc;
margin: auto;
padding: 2%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.btn-bot {
position: absolute;
bottom: 0px;
}
<div class=Center align='center'>
<button class='btn-bot'>Bottom button</button>
</div>
Give the parent element…
display: table; text-align: center;
…and its child element…
display: table-cell; vertical-align: bottom;
This way you do not need to know the width of the child element in case it changes, thus requiring no negative margins or workarounds.
For example write like this if you have position absolute:
.btn-bot{
position:absolute;
margin-left:-50px;
left:50%;
width:100px;
bottom:0px;
}
Note: give margin-left half of the width of the button.
JSFiddle demo
Does the button need to be absolutely positioned? If so, you could specify a width and then a negative left margin:
.btn-bot{
position: absolute;
left: 50%;
width: 100px;
margin-left: -50px;
bottom:0px;
}
fiddle
You can use display: table-cell and vertical-align: bottom to achieve this, although you need a container div set to display: table.
HTML
<div class="boxContainer">
<div class="box">
<button>Bottom button</button>
</div>
</div>
CSS
.boxContainer {
display: table;
}
.box {
width: 200px;
height: 200px;
background: #0088cc;
padding: 2%;
display: table-cell;
text-align: center;
vertical-align: bottom;
}
Demo
One way of doing this would be to give it an absolute width and then a margin half of that:
width: 250px;
margin-left: -125px;
Another way would be to give the div the following line-height and remove all styles from the button:
line-height: 398px;
I know this has been answered a long time ago, but I couldn't use display:table on the parent container so I had to find another way around.
It turned out that this worked just fine:
.container{
position:absolute;
}
.button{
position:absolute;
bottom: 5px;
left: 0%;
right: 0%;
text-align: center;
}
Edit: This works if your button is a <div>, not for an actual <button>
I used table-row to combine text and button in one container:
#out{
display:table;
position:absolute;
}
#out div#textContainer{
display:table-row;
}
#out div#text{
display:table-cell;
vertical-align:top;
}
#out div#buttonContainer{
display:table-row;
text-align:center;
}
#out div#button{
display:table-cell;
vertical-align:bottom;
}
CodePen
This is what worked for me and I think is what several people were trying to get at.
Just use a full width wrapper div with the button centered inside it.
<div class="outer">
<div class="inner-button-container">
The Button
</div>
</div>
.outer{
position:relative;
height:200px;
width:500px;
background-color:lightgreen;
}
.inner-button-container{
background-color:grey;
position:absolute;
bottom:0;
right:0;
left:0;
text-align:center;
}
a{
margin:auto;
background-color:white;
}
Result:
Fiddle
You can use align-items: flex-end like so:
html,
body {
height: 100%;
}
.flex-container {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.center {
width: 200px;
height: 200px;
background: #0088cc;
display: flex;
align-items: flex-end;
}
.btn-bot {
margin: 0 auto;
display: block;
}
<div class="flex-container">
<div class="center">
<button class="btn-bot">Bottom button</button>
</div>
</div>

Resources