I am building a site that works fine in both Chrome and Safari, but am having difficulties in Firefox. The applicable HTML in this issue is simple, is is just three divs inside of another div. The goal is to have one div positioned at the top of the parent div, one at the bottom, and one stretching across the remaining space:
<div class="outer">
<div class="top">
<p>some junk here</p>
</div>
<div class="middle">
<img src="<?php echo(htmlspecialchars($image_url)); ?>"/>
</div>
<div class="bottom">
<p>more junk</p>
</div>
</div>
Now, the css is as follows:
.outer {
position: relative;
display: inline-block;
text-align: center;
width: 600px;
height: 600px;
}
.middle {
background-size: 100%;
top: 62px;
bottom: 62px;
right: 0;
left: 0;
margin: 0;
padding: 0;
position: absolute;
}
.middle img {
position: absolute;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
max-width: 95%;
max-height: 95%;
}
.top, .bottom {
width: 100%; /* THIS IS WHAT IS NOT WORKING */
height: 60px;
margin: 0;
padding: 0;
display: table;
position: absolute;
}
.top {
top: 0;
}
.bottom {
bottom: 0;
}
The issue is that the top and bottom divs are not extending to 100%. The are taking up as little space as necessary to fit their content. I have tried setting a max width on the divs, tried changing the display types, but nothing works. The kicker is, once I resize the window even the smallest amount, the top and bottom divs shoot to 100%. Strange. I am at a loss with this one so any help is greatly appreciated. Thanks.
.outer DIV cannot be display: inline-block for this scenario. inline-block means to adapt to the child widths. You need to either specify an exact width dimension, or use block display property.
.outer {
position: relative;
display: block; /* use BLOCK here instead of inline-block; */
text-align: center;
}
The reason why the top and bottom divs' widths were not working properly was because they were set to a display type of table. Removing just that line fixed the issue.
.top, .bottom {
width: 100%;
height: 60px;
margin: 0;
padding: 0;
/* REMOVE: display: table; */
position: absolute;
}
Related
The last two days I've been reading most questions here and a lot more about 'fill remaining width' and 'escaping overflow: hidden', but I can't get my problem solved. At the moment, I seriously doubt if it is possible at all.
I have a scrolling box with full body width. On top of that I have a absolute positioned header that I need to make the exact same width as the scrollbox. My intention is to make the header 0px or (if needed) 1px in height and let the content overflow.
Here is a fiddle.
The scrollbox has a scrollbar (always visible), the header obviously not. To compensate for that, I float a fake scrollbar to the right inside the header container, and left of that a <div> filling the remaining width (being exactly the innerwidth of the scrollbox).
HTML
//THE SCROLLBOX
<div id="scrollbox">
<div id="center2">
content<br>content<br>...
</div>
</div>
// THE HEADER
<div id="header_box">
<!--- FAKE SCROLLBAR -->
<div id="scroller">
<div></div>
</div>
// REMAINING WIDTH
<div id="container">
<div id="FIRST">
<div id="FIRST_banner"></div>
</div>
</div>
<div id="SECOND">
<div id="SECOND_banner"></div>
</div>
</div>
</div>
CSS
#header_box {
background: yellow;
position: absolute;
left: 0;
top: 0;
right: 0;
height: 25px;
width: 100%;
overflow: visible;
}
#scroller {
float: right;
overflow-x: hidden;
overflow-y: scroll;
height: 50px;
width: auto;
/* visibility: hidden; */
}
#scroller>div {
width: 0px;
height: 101%;
}
#container {
display: inline;
width: auto;
height: 50px;
overflow: visible;
}
#FIRST {
position: relative;
overflow: hidden;
height: 25px;
background: pink;
}
#FIRST_banner {
position: absolute;
top: 0;
left: 50%;
height: 220px;
width: 30px;
background: crimson;
}
#SECOND {
background: darkcyan;
position: relative;
height: 5px;
}
#SECOND_banner {
position: absolute;
top: 0;
left: 50%;
height: 220px;
width: 30px;
background: blue;
}
The problem lies in the div (#FIRST) with remaining width. From all the solutions I've read only the one with
position: relative;
overflow: hidden;
works for me. It gives the exact width, lining up the center of the header and the scrollbox nicely. But I can't break out of the overflow: hidden, so it cuts off the content.
So my second thought was: wrap #FIRST in a #container and let the child determine the width of the parent. After that, I can put another div (#SECOND) inside the container with the width of the parent. It works partially. The #container has the width intended, and the #SECOND div overflows nicely but takes on the width of #header_box, as no width is set on the parent itself.
So, my questions:
Can I somehow break out of the overflow: hidden of the FIRST div? (In that case the container and second div can be removed).
Is there a way to let the SECOND div obey the width of it's parent.
Some totally different solution.
Sadly there is a catch to this all:
css only
no javascript
no flexbox
Thanks voor any toughts.
In the end, it was the good old <table> that saved the day, much simpler than I tought. There still is a fake scrollbar, but the absolute header now aligns perfect with the contents of the scrollable div behind it, and it remains fluid.
See fiddle here
HTML:
<!--- HEADER -->
<div id="THIRD">
<div id="THIRD_A">
<div id="THIRD_B"></div>
<div id="THIRD_C"></div>
<div id="THIRD_D"></div>
</div>
</div>
<!--- FAKE SCROLLBAR -->
<div id="scroller">
<div></div>
</div>
</div>
CSS:
/* The container for the header */
#header_box{
position: absolute;
left: 0;
top: 0;
right: 0;
height: 0px;
width: 100%;
overflow: visible;
display: table;
}
/* Takes on the width of its child: the fake scrollbar */
#scroller {
display: table-cell;
float: right;
overflow-x: hidden;
overflow-y: scroll;
height: 0px;
width: auto;
}
/* This triggers a scrollbar to be shown */
#scroller>div {
width: 0px;
height: 101%;
}
/* The 'remaining width' container (= screenwidth - scrollbar, equals innerwidth of scrollbox) */
#THIRD{
display: table-cell;
width: 100%;
height: 0px;
}
/* Needed to give the children a 'width' reference */
#THIRD_A{
position: relative;
width: 100%;
height: 0px;
}
/* The actual header items */
#THIRD_B {
position: absolute;
top: 0;
left: 50%;
width: 25px;
height: 220px;
background: black;
}
#THIRD_C {
position: absolute;
top: 0;
left: 10%;
width: 125px;
height: 120px;
background: black;
}
#THIRD_D {
position: absolute;
top: 0;
right: 0%;
width: 25px;
height: 220px;
background: black;
}
NOTE:
On most handheld browser, this is 1px off. It seems webkit based browsers display a tablecell of 0px width as 1px width (see this question). The solution is to wrap the table in another div with css:
position absolute;
left: 0;
right: -1px
and setting #scroller>div to a width of 1px.
NOTE 2:
This is also a solution for a fixed div inside a scrollable div. See this fiddle
So i have .cont that's centered in using position absolute and is height 80% of body.
Inside it there are two divs. One is fixed height. And other one needs to expand to rest of parent, .cont.
So How do i make it expand to parent.
One other requirement is that content in both of these needs to be vertically and horizontally centered.
body
.cont
.top
.fillRest
Here is jsfiddle: http://jsfiddle.net/24jocwu5/
make .fillRest Expand to rest of .cont.
vertically and Horizontally center h1 headings in both divs.
Don't Use calc()
can use display table, flow, position, and other tricks.
Here you go. Absolutely position the white container with a top-padding that equals the height of your fixed-height top div. Then give the top div a z-index so it goes over your white box:
Fiddle - http://jsfiddle.net/24jocwu5/2/
* {margin: 0; padding: 0;}
html, body {
height: 100%;
background-color: #3dd;
color: #aaa;
font-family: helvetica;
}
.cont {
position: absolute;
top: 0; bottom: 0;
right: 0; left: 0;
background-color: #1af;
width: 400px;
margin: auto;
height: 80%;
}
.top {
height: 100px;
background-color: pink;
position: relative;
z-index: 1;
}
.fillRest {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding-top: 100px;
height: 100%;
background-color: #fff;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
h1 {
text-align: center;
width: 200px;
margin: auto;
background-color: #eee;
}
You can use flexbox for this
.cont {
display: flex;
flex-direction: column;
}
.cont > div {
display: flex;
}
.fillRest {
flex: 1;
}
Working Fiddle
This is what you want?
Only position fixed and right and left 0
http://jsfiddle.net/pabliiitoo/24jocwu5/1/
.fillRest {
position: fixed;
left: 0;
right: 0;
background-color: red;
min-height: 80px;
}
In order to expand the .fillRest to the rest of its parent .cont, you need to set it's height to a percentage. I estimate about 20~30% is what you want in order to maintain a similar look to the image you've provided here.
To test it, grab a very large paragraph full of letters and anything you want and put it where the 'Content' text is, that way you will be able to see it expanding in a responsive way. Another suggestion I will give you is to make your width percentages as well, so that they expand according to the width of the screen responsively.
Let me know if this helped you, otherwise I can take another look :)
CSS
.cont {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
background-color: #1af;
width: 400px;
margin: auto;
height: 80%;
}
Personally, I think the way you're going about this is all wrong. But maybe something like this would work.
http://jsfiddle.net/24jocwu5/5/
CSS selectors I changed:
.cont {
position: absolute;
top: 0; bottom: 0;
right: 0; left: 0;
background-color: #1af;
width: 400px;
margin: 10% auto;
overflow: hidden;
}
.top {
height: 20%;
background-color: rgba(255,255,255,.8);
}
.fillRest {
background-color: white;
position: relative;
width: 100%;
height: 80%;
}
h1 {
text-align: center;
width: 100%;
margin: auto;
background-color: #eee;
}
This is Summary Of Ways.. First two ways posted here--
FlexBox Method 100% WORKS
Padding Method 80% WORKS. Useful But not exactly.
Css Table Cell and Table Rows 100% WORKS. From Me.
Using Calcs Simplest One. 100% WORKS. From me.
Css Table Cell: http://jsfiddle.net/24jocwu5/7/
.cont is The Table. top & fillRest are table rows, and there is cell which can have vertical align middle.
Calc Method: http://jsfiddle.net/24jocwu5/9/
Works but doesn't scale well if content increases, so need to use another div which can contain the content. Like so http://jsfiddle.net/24jocwu5/10/
Default code:
* {margin: 0; padding: 0; }
html, body {
height: 100%;
background-color: #3dd;
color: #aaa;
font-family: helvetica;
}
.cont {
position: absolute;
top: 0; bottom: 0;
right: 0; left: 0;
background-color: #1af;
width: 400px;
margin: auto;
height: 80%;
}
html:
<div id="main">
<div style="position: absolute; height: 150px; width: 400px; left: 290px;"><img src="HEAD-IMAGE.jpg" /></div>
<div style="position: absolute; height: 300px; width: 233px; top: 180px;"><img src="LEFT-IMAGE.jpg" />(below head)</div>
<div style="position: absolute; top: 200px; left: 270px;">TEXT (next to left image)</div>
</div>
css:
div#main{
position: absolute;
top: 141px; left: 50%;
height: 100%; width: 960px;
padding: 10px;
margin-left: -490px;
text-align: justify;
background-color: yellow;
}
my padding from #main works for my images but not for my text (right & bottom padding).
Why is this happening?
In your example, only the text div has a top and left property. The two divs containing the images only contain one of these properties:
The header div has left: 290px;, so it gets its y-axis position moved by the top padding.
The left div has top: 180px; so it gets its x-axis position moved by the left padding.
The text div has top: 200px; left: 270px; so its x and y-axis are not affected by the padding.
To illustrate this, for this example the text div has had its left property removed. It is now affected by the left padding of its container:
("Show code snippet" and run it)
#main {
position: absolute;
top: 141px;
left: 50%;
height: 100%;
width: 960px;
padding: 50px;
margin-left: -290px;
text-align: justify;
background-color: yellow;
}
.header {
position: absolute;
height: 150px;
width: 400px;
left: 290px;
background: #F00;
}
.left {
position: absolute;
height: 300px;
width: 233px;
top: 180px;
background: #F00;
}
.text {
position: absolute;
top: 200px;
background: #F00;
}
<div id="main">
<div class="header">
<img src="http://www.placehold.it/200" />
</div>
<div class="left">
<img src="http://www.placehold.it/200" />
</div>
<div class="text">You can't handle the truth, soldier!</div>
</div>
Is position: absolute the best way to layout my elements?
Depends... position: absolute removes elements from the normal flow of the document. That is, each element is essentially invisible to the other. This is particularly problematic if you wish to create a flexible layout, which can re-size in accordance with the users browser height / width.
Can you show me another way to layout HTML elements?
Sure! There are many ways to layout a page without resorting to position: absolute. Here is a basic example using display: flex — a newer way to layout elements. It does not enjoy 100% browser support yet, so this is purely an example of one technique :)
Read more:
about vw and vh units on the MDN
about flexbox over on CSS-Tricks - A Complete Guide to Flexbox
about flexbox browser support
Flex example
Note how the elements resize when the example is made full-screen.
* {
margin: 0;
padding: 0;
}
body {
width: 80vw;
max-width: 800px;
margin: 0 auto;
background: #424242;
}
header {
background: #e91e63;
height: 20vh;
}
.wrap {
display: flex;
}
.left {
background: #fce4ec;
flex: 1;
}
.content {
background: #fafafa;
min-height: 70vh;
flex: 2;
}
footer {
height: 10vh;
background: #c51162;
}
<header>
I am header
</header>
<div class="wrap">
<div class="left">
I am sidebar
</div>
<div class="content">
I am content
</div>
</div>
<footer>
I am footer, hear me roar! RWAR!
</footer>
Define a class .child for your <div>
<div class="child">
and define style accordingly
.child { padding: 10px; }
Use position: relative; on the child divs to make them account for the parent divs padding.
problem is you give left and top to text div that why not accept padding,simply remove left to text div then it will accept the padding...
I have a modal dialog for a workflow that displays content roughly of a fixed height, but also displays an embedded PDF for a user to review.
I'd like to maximize the height of the PDF for the user's screen size, so the dialog scales vertically, but I can't get the PDF to fill all the remaining space within the dialog's div.
Here is the Html:
<div class="container">
<div class="popUp">
<div class="popUpHeader">Header</div>
<div class="fixedContent">Fixed Height Content</div>
<div class="resizeableContent">I should fill all the free vertical space in .popUp</div>
<div class="popUpFooter">Footer</div>
</div>
</div>
and CSS I'm using:
body, html {
margin: 0;
height: 100%;
}
.container {
height: 100%;
min-height: 100%;
background: #F8F8FF;
}
.popUp {
background: lightgrey;
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 70%;
height: 90%;
}
.popUpHeader {
width: 100%;
background: darkgrey;
text-align: center;
}
.popUpFooter {
width:100%;
background:darkgrey;
text-align:center;
position: absolute;
bottom: 0;
}
.fixedContent {
height: 10em;
text-align: center;
background: #E1E1EE;
}
.resizeableContent {
background: #7d7f7c;
text-align: center;
width: 100% height: 100%;
}
JsFiddle: http://jsfiddle.net/trainman1124/pnbeoyb9/2/
Here is an image of the desired result:
Edit
Here is a sample JsFiddle using an embedded PDF, which is what actually needs to be done.
http://jsfiddle.net/trainman1124/pnbeoyb9/3/
Note, I've corrected the missing semicolon in the example and also added overflow:hidden
You could use the display: table; and display: table-row properties in order to fill the space.
Set the .container to fill 100% of the page and .popUp div to display: table; and fill it's parent.
Display all the children as display: table-row;, and then set heights for the popUpHeader and popUpFooter divs.
Allow your resizableContent div to fill the remaining space:
.resizeableContent {
background: #7d7f7c;
width: 100% height: 100%;
display: table-row;
}
Check out this CodePen
Modify Popup class to make its color same as resiseableContent
.popUp {
background: #7d7f7c; /* Modified here */
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 70%;
height: 90%;
overflow: hidden;
}
Depending on what browsers you need to support (This wont work earlier than IE9), one solution would be to use calc and vh units.
Something like:
.popUp {
background: lightgrey;
margin: auto;
height: calc(100vh - 10em); /* Height of viewport minus your .fixedContent div, you may also want to include the height of the header */
overflow: hidden;
}
The updated fiddle has the heights set to % instead. That works as you want I think?
Update
http://jsfiddle.net/batcave/pnbeoyb9/7/
.popUpFooter {
width:100%;
background:darkgrey;
text-align:center;
position: absolute;
bottom: 0;
height: 7%;
}
.resizeableContent {
background: #7d7f7c;
text-align: center;
width: 100%;
height: 80%;
}
.fixedContent {
height: 10%;
text-align: center;
background: #E1E1EE;
}
I am trying to achieve following with my code: I would like to have a div container, div#title-box, that is centered. Inside that div container I want to have 3 other div containers, div#logo, div#title, div#subtitle (look at the code to see how exactly they are displayed)
Now the actual problem: The div#logo has a given width, the other two however don't, they float.
How can I have have the div#title-box wrap around the other three divs but at the same time staying centered. Another problem I see is that the div#title-box cannot have a fixed width.
Any ideas. Thanks!
EDIT: The code below has to be modified so that the div#title-box wraps around the other divs and stays centered.
If anyone needs to play around with the code, here is it with a full example:
<!DOCTYPE html>
<html>
<head>
<style>
div#title-box {
max-width: 500px;
display: block;
height: 600px;
margin: 0 auto;
position: relative;
}
div#logo {
padding: 0;
margin: 0;
position: absolute;
top: 100px;
left: 5px;
width: 100px;
height: 100px;
overflow: auto;
background: #ff0000 no-repeat;
background-size: 100% 100%;
border-radius: 15px;
float: left;
}
div#title {
padding: 0;
margin: 0;
position: absolute;
left: 110px;
top: 100px;
bottom: 20px;
right: 10px;
overflow: auto;
float: left;
}
div#subtitle {
padding: 0;
margin: 0;
position: absolute;
top: 140px;
bottom: 20px;
right: 10px;
left: 110px;
overflow: auto;
float: left;
}
</style>
</head>
<body>
<div id="title-box">
<div id="logo">
</div>
<div id="title">
<h1>Hello</h1>
</div>
<div id="subtitle">
<h3>A A A A A A A A A A A A A A A!</h3>
</div>
</div>
try something along the lines of
div#title-box {
width: 500px;
display: inline-block;
height: 600px;
margin: 0 25%;
position: relative;
left:-250px;
}
When you apply
position: absolute
to your code, it will be put out of the rest of the DOM-context.
I have modified your CSS as such: http://jsfiddle.net/asBmS/. Your wrapping div now should always contain the child divs. Is this what you wanted?
The best thing I can think to suggest is more of a 'hack' which would need to be adjusted if you change the width of the content.
Take a look at this link and see the offset margin-left, it puts everything in the center.
You'll probably need to tweak it further to meet your needs.
http://jsfiddle.net/asBmS/15/
#logo,#title,#subtitle{
/*offset hack*/
margin-left: 10% !important;
}