I've stumbled upon some unexpected behaviour when testing a layout in Firefox. It seems that when a parent is set to display:table-cell and position:relative, its children do not respect the parent width when positioned absolutely and given 100% width. Instead, the child width is set to the parent's parent width. I've recreated this issue with a fiddle:
http://jsfiddle.net/D6Rch/1/
which is structured as:
<div class="table">
<div class="cell-1">
<div class="content-1">this must be positioned absolutely</div>
<div class="content-2">as these divs will be overlapping</div>
</div>
<div class="cell-2">
<div class="advert">fixed width advert</div>
</div>
</div>
.table {
width:600px;
height:400px;
border:3px solid black;
display: table;
position: relative;
table-layout: fixed;
}
.cell-1 {
width: auto;
display: table-cell;
background: yellow;
position: relative;
margin-right:10px;
}
.cell-2 {
margin-right:10px;
width: 100px;
display: table-cell;
background: pink;
position: relative;
}
.content-1 {
position: absolute;
top: 10px;
width: 100%;
background: lightgreen;
z-index: 5;
}
.content-2 {
position: absolute;
top: 50px;
width: 100%;
background: lightblue;
z-index: 5;
}
.advert {
position: relative;
border: 1px solid red;
}
It functions as expected in Chrome & Safari, but not on Firefox. Question is, why does this happen? And is there a workaround for this or should I take an altogether different approach?
Thanks in advance,
This is a known bug in Gecko. See the Gecko Notes here - https://developer.mozilla.org/en-US/docs/Web/CSS/position
So, you'll have to wrap you content divs in another positioned div. Like so
http://jsfiddle.net/D6Rch/4/
<div class="cell-1">
<div class="wrapper">
<div class="content-1">this must be positioned absolutely</div>
<div class="content-2">as these divs will be overlapping</div>
</div>
</div>
.wrapper {
position: relative;
}
Related
There are lots of card to be showed and I need to show menu when I hover one of the cards.
I use position: absolute; for menu and use position: relative; for the card, but why the scrollbar appeared when I hover on the card ?
<!DOCTYPE html>
<html>
<head>
<style>
.box {
height: 240px;
width: 200px;
overflow: auto;
border: 1px dashed red;
}
.card {
height: 120px;
width: 120px;
border: 1px solid blue;
position: relative;
}
.menu {
display: none;
height: 400px;
width: 200px;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(orange, pink);
}
.card:hover .menu {
display: block;
}
</style>
</head>
<body>
<div class="box">
<div class="card">
<div class="menu"></div>
</div>
</div>
</body>
</html>
The scrollbar has nothing to do with your positioning, it is a result of overflow: auto; on your .box element.
overflow: auto; will show a scrolling bar if a child element overflows its parent container where overflow: auto; is set.
Seeing as the .box parent-element has a fixed size value height: 240px; while its child element .menu has height: 400px;, it will cause a scrollbar to appear because there is an overflow of 160px.
While #Yong is correct with document flow in his answer with the position: absolute; property, seeing as you have fixed height and width on all your elements, position: absolute; doesn't actually do anything in this exact reproducible example.
If I understand your problem correctly, a simple solution to your problem if you want to keep the fixed width and height on your .box element, you can simply disable the scrollbar by applying display: none; to the .box pseudo-element ::-webkit-scrollbar.
(NOTE: As of February 28th, 2022 this is still not supported in Firefox).
Read more about browser support at https://caniuse.com/?search=%3A%3A-webkit-scrollbar
Example with no positioning properties & -::webkit-scrollbar
.box {
height: 240px;
width: 200px;
border: 1px dashed red;
overflow: auto;
}
.box::-webkit-scrollbar{
display: none;
}
.card {
height: 120px;
width: 120px;
border: 1px solid blue;
/*position: relative;*/
}
.menu {
display: none;
height: 400px;
width: 200px;
/*position: absolute;
top: 0;
left: 0;*/
background: linear-gradient(orange, pink);
}
.card:hover .menu {
display: block;
}
<!DOCTYPE html>
<html>
<body>
<div class="box">
<div class="card">
<div class="menu"></div>
</div>
</div>
</body>
</html>
If you want to remove overflow altogether, you can apply overflow: hidden; to .box.
Keep in mind the fixed height of 400px on the .menu element will not apply as the fixed height of 240px on the .box element will hide the remaining 160px. I hope this solves your problem, but a little more detail would help!
absolute
The element is removed from the normal document flow, and no space is
created for the element in the page layout. It is positioned relative
to its closest positioned ancestor, if any; otherwise, it is placed
relative to the initial containing block. -MDN
.menu is positioned absolute therefore it is positioned relative to .card which is the closes positioned ancestor to it.
relative
The element is positioned according to the normal flow of the
document, ... -MDN
And because .card is positioned relative it would still take space and position according to the normal flow of the document. Therefore, it would still be taken into consideration whether the .box or its parent would overflow or not.
with set position: absolute; for .menu and position: relative; for .card you able to change the position of .menu with top bottom left right properties relative to its first positioned (not static) ancestor element( .card position ).
but in your question, the absolute or relative position is not the cause of the scrollbar appear . The reason is the owerflow property .
the default value for owerflow is visible that create no owerflowing . And you created the scrollbar by setting it auto because the size of menu is larger than card.
.box {
height: 240px;
width: 200px;
/* overflow: auto; */
border: 1px dashed red;
}
.card {
height: 120px;
width: 120px;
border: 1px solid blue;
position: relative;
}
.menu {
display: none;
height: 400px;
width: 200px;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(orange, pink);
}
.card:hover .menu {
display: block;
}
<div class="box">
<div class="card">
<div class="menu"></div>
</div>
</div>
How can I achieve the styling shown in the picture? Consindering the following scenario: I got 2 nested div elements, by which the parent is "relative positioned" and the child is "absolute positioned"! And the child div is always "fixed to the bottom" of the body element, when browser is scaled. I don't get this to work...
Here is the code, where I am using padding-bottom: 100%. But this is not a good solution! Is there a way to realise this with only CSS 2.1 API?
body {
min-height: 100%;
background-color: grey;
}
.parent {
height: 70px;
width: 440px;
left:200px;
background-color: blue;
position: relative;
}
.child {
display: block;
position: absolute;
width: 100px;
right:0px;
background-color: yellow;
padding-bottom: 100%;
}
<body>
<div class="parent">
<div class="child">Fix to bottom</div>
</div>
</body>
Don't take 2nd div as child. You want it to stick to bottom and parent div's height will disturb it while scalling.
I hope this helps :)
body {
min-height: 100%;
background-color: grey;
}
.parent {
height: 70px;
width: 400px;
left:100px;
background-color: blue;
position: relative;
top:70px;
}
.another-parent {
display: block;
height:60%;
position: absolute;
bottom:0;
width: 100px;
right:22%;
background-color: yellow;
}
<body>
<div class="parent"></div>
<div class="another-parent">Fix to bottom</div>
</body>
What's the best way to achieve this:
I have two elements, both absolutely positioned and I want the child to overlap horizontally, even though its parent has overflow-x: hidden.
FIDDLE
.parent {
position: absolute;
z-index:1;
height: 100%;
min-height: 300px;
overflow-y:auto;
overflow-x:hidden;
width: 200px;
background: #ccc;
}
.child {
position:absolute;
z-index:2;
width: 300px;
height: 100px;
top: 30px;
left: 10px;
padding: 10px;
background: #555;
color: white
}
Add a third div that is a parent of both. Position both items absolutely within the outer parent.
<div class="outer-parent">
<div class="parent">
</div>
<div class="child">
</div>
</div>
I have a in my webpage which carries 2 images. I want one image to be aligned left and other to the right end of the division.
The JsFiddle
Here's my HTML:
<div class="header">
<img id ="ttl" src="Home_files/images/ttl.png">
<img id ="se" src="Home_files/images/se.png">
</div>
and CSS:
.header {
position: relative;
top: 0%;
height: 20%;
}
/*Header CSS*/
img#ttl {
position: relative;
top:50%;
height: 50%;
left: 0px;
}
img#se {
position: relative;
top:60%;
height:30%;
vertical-align:right;
margin-right: 2%;
}
PS: I tried float:right;. Its works in in Chrome and FF but not in IE.
And ofcourse this div has a parent div. But I don't think that will be a problem.
You can wrap the images inside a position relative container and use position: absolute; to position them to bottom left and bottom right
Demo
<div class="wrap">
<img src="http://images.google.com/intl/en_ALL/images/logos/images_logo_lg.gif" />
<img src="http://images.google.com/intl/en_ALL/images/logos/images_logo_lg.gif" />
</div>
div.wrap {
width: 600px;
border: 1px solid #f00;
height: 300px;
position: relative;
}
.wrap img {
border: 1px solid blue;
position: absolute;
bottom: 0;
}
.wrap img:nth-of-type(1) {
left: 0;
}
.wrap img:nth-of-type(2) {
right: 0;
}
Note: Am using nth-of-type to select images so that I don't have to
declare classes for each image, if you want to support older browsers,
you need to add class for each image and replace :nth-of-type with
those classes
try this
<div class="header">
<div class="left"><img id ="ttl" src="Home_files/images/ttl.png"></div>
<div class="right"><img id ="se" src="Home_files/images/se.png"><div>
</div>
CSS
.left{
float:left;
}
.right{
float:right;
}
Demo
I used a table in a basic HTML header div for an email. It worked fine. In tr, had one image on left as td and another on right with float: right in another td.
Is there any css property like min-height, but for top?
In the example below, when i hide div1 (via javascript), i want div2 to have top:50. Else, to be placed below div1.
<html>
<head>
<style>
#div1
{
height:100px;
}
#div2{
//min-top:50px;
}
</style>
</head>
<body>
<div id='div1'>This div may be hidden</div>
<div id='div2'>This div must not be placed above 50px</div>
</body>
</html>
Edit: as i answered below
When div1 is not hidden i want div2 to be exactly below div1. imagine div1 as a treeview which can have any height (or even be hidden) and div2 as a paragraph which should always be below 50px
I came up with this solution which utilises the top:0 bottom:0 hack.
We create a container the height of it's relative parent (if any) - we then give this a min-height (eg your min-top)
We then position the actual element absolutely to the bottom on this container.
CSS:
.container {
position:absolute;
bottom:0px;
top: 0;
min-height: 700px; //Adjust this to your MINIMUM (eg your min-top)
}
.position-me {
position: absolute;
bottom: 0;
}
HTML:
<div class="container">
<div class="position-me">Great!</div>
</div>
"Is there a css min-top property?" no, but ...
... you can use math function to take effect like min-top:
<style>
#div2{
top:max(50px, 10%);
}
</style>
https://developer.mozilla.org/en-US/docs/Web/CSS/max
No there's nothing like min-top
Instead you can use is
div {
position: relative;
top: 50px;
}
And for the example you shown visibility: hidden; will be best suited here, as it will reserve the space of your hidden div
I suspect that this will do the trick for you but I believe it is not a very good practice:
#div1
{
height:100px;
outline: 1px solid red;
margin-bottom:-50px;
}
#div2{
margin-top:50px;
outline: 1px solid blue;
}
DEMO: http://jsfiddle.net/pavloschris/tbbvU/
( Just comment/uncomment the display:none to see it work.)
I see that this question has still many views and people are still commenting. Because of the fact that the question is not fully answered, i decided to write here the complete answer:
Appropriate css:
#div1 {
min-height:50px;
background-color: #fee;
margin-bottom:-50px;
}
#div2 {
margin-top:50px;
background-color: #efe
}
http://jsfiddle.net/vVsAn/5051/
Results
When div1 is hidden, div2 has a top property of 50px
When div1 is not hidden:
If div1 height is less than 50px, then div2 is placed at 50px
If div1 height is more than 50px, then div2 is placed right under div1
$(window).on("resize", function () {
if ($('#div1').css('display', 'none')){
$("#div2").addClass('minTop');
} else if ($('#div1').css('display', 'block')){
$("#div2").removeClass('minTop');
}
}).resize();
#div1{
width:100px;
height:100px;
background-color:#ff0000;
position:absolute;
display:block;
/* display:none; */
}
#div2{
width:100px;
background-color:#ffff00;
top:150px;
position:absolute;
}
#div2.minTop{
top:50px !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<div id='div1'>div 1</div>
<div id='div2'>div 2</div>
</body>
</html>
Solution using margins
See also solution using position:sticky.
The following solution uses a css3 selector "directly preceded by" or "placed immediately after" and it works by toggling a predetermined class (.hidden in this example) on the preceding element.
#div1.hidden + #div2 {
margin-top: 50px;
}
.hidden {
display: none;
}
const toggle = () => div1.classList.toggle('hidden')
#div1.hidden + #div2 {
margin-top: 50px;
}
.hidden {
display: none;
}
div {
border: 1px solid red;
height: 100px;
margin-bottom: 10px;
}
section {
position: absolute;
border: 1px solid blue;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 10px;
overflow: hidden;
margin: 5px;
}
aside {
position: absolute;
top: 40px;
right: 20px;
z-index: 1;
display: flex;
flex-direction: column;
}
<section>
<div id='div1'>This div may be hidden</div>
<div id='div2'>This div must not be placed above 50px</div>
</section>
<aside>
<button type="button" onclick="toggle()">Toggle #div1</button>
</aside>
Solution using position: sticky
See also solution using margins.
To achieve somewhat similar you can use position: sticky. It's not exactly same as top-min would have ideally been, but it can be tweaked cleverly with parent styles to achieve what you have in mind.
.sticky {
/* Note: The parent element must have a non-default position set too. */
position: sticky;
top: 50px;
}
Note: The parent of position:sticky element must have a non-default position set as well.
What this does is that when the element moves up by either scrolling, reducing viewport height or layout changes, it will stick to the defined position and will not move until the parent element itself crosses the boundary and pushes the element out of the way (as seen in animation below).
const toggle = () => div1.classList.toggle('hidden')
const toggleSticky = () => div2.classList.toggle('sticky')
.sticky {
position: sticky;
top: 50px;
}
.hidden {
display: none;
}
section {
/* Note: The parent of position:sticky element must have a non-default position set. */
position: absolute;
border: 1px solid blue;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 10px;
overflow: hidden;
margin: 5px;
}
div {
border: 1px solid red;
height: 100px;
margin-bottom: 10px;
}
aside {
position: absolute;
top: 40px;
right: 20px;
z-index: 1;
display: flex;
flex-direction: column;
}
<section>
<div id='div1'>This div may be hidden</div>
<div id='div2' class="sticky">This div must not be placed above 50px</div>
</section>
<aside>
<button type="button" onclick="toggle()">Toggle #div1</button>
<button type="button" onclick="toggleSticky()">Toggle #div2 sticky</button>
</aside>