Fixed element relative to parent - css

I have included a code snippet, I'm trying to position the header and footer so that it is inside of the .main div.
I have no idea why this isn't working. Instead it is spanning across the whole of the viewport.
In this particular layout I can't determine the left position of the parent without JavaScript and I wish to keep it at CSS.
The header and footer should stay in the same place as they are when scrolled.
.main {
position: absolute;
left: 60px;
right: 0px;
top: 0px;
height: 50000px;
background-color: #09f;
}
.parent {
position: relative:
width: 100%;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
background-color: #f00;
}
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #f00;
}
<div class="main">
<div class="parent">
<div class="header">
<h3>header</h3>
</div>
<div class="footer">
<h3>footer</h3>
</div>
</div>
</div>
Thanks for any help in advance,
Jamie

As I wrote in the comment under question, fixed width is counted to viewport, not the parent element. But you can set left: 60px (the same value as content has) to fixed elements.
.main {
position: absolute;
left: 60px;
right: 0px;
top: 0px;
height: 50000px;
background-color: #09f;
}
.parent {
position: relative:
width: 100%;
}
.header {
position: fixed;
top: 0;
left: 60px;
right: 0;
background-color: #f00;
}
.footer {
position: fixed;
bottom: 0;
left: 60px;
right: 0;
background-color: #f00;
}
<div class="main">
<div class="parent">
<div class="header">
<h3>header</h3>
</div>
<div class="footer">
<h3>footer</h3>
</div>
</div>
</div>

Related

Mix-blend-mode working when applied to one element but not another

I am using mix-blend-mode on css-generated content to create a multiplied background effect.
When I apply this generated element to an outer wrapper it has the intended effect:
.standard-cover {
background: blue;
color: #fff;
position: absolute;
top: 0;
left: 0;
width: 100%;
min-height: 100%;
display: flex;
}
.standard-cover:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
.image-wrap {
line-height: 0;
}
img {
object-fit: cover;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
.content-wrap {
position: relative;
text-align:center;
z-index: 30;
min-height: 1em;
margin: auto;
padding: 3.33%;
}
<div class="standard-cover">
<div class="image-wrap">
<img src="http://placeimg.com/480/480/nature" alt="Nature">
</div>
<div class="content-wrap">
<div class="content">
<h2>A title</h2>
<p>A pagragraph</p>
</div>
</div>
</div>
When I apply it to an inner wrapper it does not:
.standard-cover {
position: absolute;
background: blue;
color: #fff;
top: 0;
left: 0;
width: 100%;
min-height: 100%;
display: flex;
}
.image-wrap {
line-height: 0;
}
img {
object-fit: cover;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
.content-wrap {
position: relative;
text-align:center;
z-index: 30;
min-height: 1em;
margin: auto;
padding: 3.33%;
}
.content-wrap:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
.content {
position: relative;
z-index: 30;
}
<div class="standard-cover">
<div class="image-wrap">
<img src="http://placeimg.com/480/480/nature" alt="Nature">
</div>
<div class="content-wrap">
<div class="content">
<h2>A title</h2>
<p>A pagragraph</p>
</div>
</div>
</div>
In both cases the actual css that applies the faux background color is identical:
.class:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
But in the first example it in fact applies the mix-blend-mode effect properly. In the second example it does not (despite inspectors confirming that the mix-blend-mode attribute is present and set to multiply).
Is there some nuance to the mix-blend-mode spec that I'm not understanding? Or am I missing some crucial something in my code?
It's all about stacking context. In the first case, the pseudo element is applied to .standard-cover where there is the background so its a child element of it and mix-blend-mode will work correctly because both belong to the same stacking context. In the second case, you moved the pseudo element to .content-wrap and there is a z-index specified so now it belong to another stacking context and mix-blend-mode will no more have effect outside.
An easy solution is to remove the z-index from .content-wrap to avoid creating a stacking context and mix-blend-mode will work like intended:
.standard-cover {
position: absolute;
background: blue;
color: #fff;
top: 0;
left: 0;
width: 100%;
min-height: 100%;
display: flex;
}
.image-wrap {
line-height: 0;
}
img {
object-fit: cover;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
.content-wrap {
position: relative;
text-align:center;
min-height: 1em;
margin: auto;
padding: 3.33%;
}
.content-wrap:after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 20;
content: "";
background: blue;
mix-blend-mode: multiply;
}
.content {
position: relative;
z-index: 30;
}
<div class="standard-cover">
<div class="image-wrap">
<img src="http://placeimg.com/480/480/nature" alt="Nature">
</div>
<div class="content-wrap">
<div class="content">
<h2>A title</h2>
<p>A pagragraph</p>
</div>
</div>
</div>
Note: Applying a blendmode other than normal to the element must establish a new stacking context [CSS21]. This group must then be blended and composited with the stacking context that contains the element. ref
I achieved the same effect by applying the mix-blend-mode: difference !important; and filter: invert(1) !important; styles to the header element of my nav-bar, the nav-bar itself has a transparent background so it only finds of the difference of the child elements against the background.

CSS, Is there anyway to prevent the children of creating their own stacking context?

Simply I want the content to scroll under the fixed header but the modal in the top of the header. if I removed the position: relative; from the .content it will work fine but I can't remove it in my real project there are hundreds of children using it and other properties creating new stacking context. thanks for help.
here is html html:
<div>
<div class="header">
</div>
</div>
<div class="content">
<div class="modal">
</div>
</div>
CSS:
.header {
position: fixed;
top: 0;
height: 100px;
width: 100%;
background: blue;
}
.content {
margin-top: 115px;
height: 1000px;
width: 100%;
background: yellow;
position: relative;
}
.modal {
position: fixed;
top: 25%;
left: 25%;
height: 50%;
width: 50%;
background: red;
z-index: 10;
}
and also fiddle

How to set initial top position when an element's position attribute is sticky

I would love to set the initial position of #box4 with a top: 45px just like the position of #box3 relative to #box2, but still keep #box4 with a position: sticky which makes it at the same level after scrolling down the page.
Initial position,
After scrolling,
html,
body {
margin: 0;
padding: 0;
height: 1000px;
}
.box {
width: 30px;
height: 30px;
border: 1px solid #bdbdbd;
}
#box1 {
position: static;
}
#box2 {
position: relative;
left: 50px;
top: -15px;
}
#box3 {
position: fixed;
top: 30px;
left: 100px;
}
#box4 {
position: sticky;
top: 30px;
left: 150px;
}
<div class="box" id="box1">
B1 Static
</div>
<div class="box" id="box2">
B2 Relative
</div>
<div class="box" id="box3">
B3 Fixed
</div>
<div class="box" id="box4">
B4 Sticky
</div>
A possible work around is to use a negative margin-top to position the #box4 into the right place.
#box4 {
margin: -15px;
position: sticky;
top: 30px;
left: 150px;
}

i would like to center a div inside another div but not working?

#first {
position: relative;
width: 20%;
height: 20%;
border-radius: 50%;
background-color: #94b8b8;
}
#second {
position: absolute;
width: 15%;
height: 15%;
border-radius: 50%;
background-color: blue;
}
<html>
<body>
<div id="first">
<div id="second">
</div>
</div>
</body>
</html>
How to get it i want the second div in the exact center of the first div but it is not even visible. how achieve this without using left, top attributes.
note:i wants align it only using css but not using tag.
To center absolutely positioned div with known width, you can use this:
.inner1 {
left: 0;
right: 0;
margin: auto;
}
Or, if you need to center it both horizontally and vertically:
.inner2 {
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
If width of inner is unknown - use css3 transforms:
.inner3 {
left: 50%;
transform: translateX(-50%);
top: 0;
}
Ant for vertical centering also:
.inner4 {
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
Fiddle demo: https://jsfiddle.net/4qxpc0ua/
calculate the top and left position and apply it for the second div.
#first {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background-color: #94b8b8;
}
#second {
position: absolute;
width: 15%;
height: 15%;
left:42.5%; //50% - (15% / 2)
top:42.5%; //50% - (15% / 2)
border-radius: 50%;
background-color: blue;
}
DEMO
There are several possibilities to do what you want:
.outer {
background: lightblue;
width: 300px;
height: 100px;
}
.inner {
background: black;
width: 100px;
height: 50px;
color: white;
}
<div class="outer" align="center">
<div class="inner">
Deprecated (use css)
</div>
</div>
<br>
<div class="outer">
<div class="inner" style="position: relative; left: 50%; margin-left: -50px;">
:)
</div>
</div>
<br>
<div class="outer" style="position: relative">
<div class="inner" style="position: absolute; left: 50%; margin-left: -50px;">
:)
</div>
</div>
<br>
<div class="outer">
<div class="inner" style="margin: 0 auto;">
</div>
</div>
Another solution
.outer {
width: 100%;
text-align: center;
}
.inner {
display: inline-block;
}

How to get scrolling content in a master page, that's in an iFrame?

Sorry, I know that's a really bad title, but I couldn't come up with a better one.
I'm trying to lay out this website using purely CSS. Previously this had been accomplished using javascript, but I know that it can be done with just CSS.
first off: here's a diagram of the intended layout:
Basically, we have a wrapper page that has a header, a footer, and an iFrame:
wrapper.aspx:
<form id="form1" runat="server">
<div id="wrapper">
<div id="divHeader">
</div>
<div id="divMain" >
<iframe id="ifrmMainBody" src="page.aspx"></iframe>
</div>
<div id="divFooter" >
</div>
</div>
</form>
then, the page that is in the iFrame, uses a master page which has a main-menu, a navigation panel, a few more toolbars, and then the content:
main.master:
<form runat="server">
<div id="mainMenu">
main menu
</div>
<div id="navPanel">
navigation panel
</div>
<div id="breadCrumb">
bread crumb
</div>
<div id="caption">
caption
</div>
<div id="subMenu">
sub-menu
</div>
<div id="toolBar">
toolbar
</div>
<div id="content">
content
</div>
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</form>
And then there's the page that uses the master page. I hard-coded in the width and height to force the scrollbars to appear:
page.aspx:
<form>
<div style="height: 1200px; width: 1500px;">
<p>
Put content here.
</p>
</div>
</form>
The problems I'm facing are:
Having problems getting the iFrame to take up the entire page height minus header and footer
Getting the scrollbars to appear ONLY in the content section
having the navigation panel and other toolbars not move when I scroll
Can anyone help me get this page laid-out correctly?
I think fixed position elements are kind of gross, because it forces the user to constantly see all your extra stuff when they might just want to see the content, but it sounds like what you're looking for. You can try something like this: http://jsfiddle.net/HBeBq/
#header {
position: fixed;
top: 0;
width: 100%;
height: 5em;
}
#navigation {
position: fixed;
left: 0;
top: 5em; // same as header height
bottom: 5em; // same as footer height
width: 10em;
}
#footer {
position: fixed;
bottom: 0;
width: 100%;
height: 5em;
}
#contentWrapper {
position: fixed;
left: 10em; // same as nav width
top: 5em; // same as header height
bottom: 5em; // same as footer height
right: 0;
overflow: auto; // if this div's contents are too big, scrollbars automatically appear
}
#content {
position: relative;
width: 2000px;
height: 2000px;
}
Adam's answer is very good. I did something similar:
/*in wrapper*/
#wrapper {
width: 100%;
height: 100%;
}
#divHeader
{
position: absolute;
top: 0px;
left: 0px;
right: 0px;
height: 30px;
background-color: #756398;
}
#divMain /*container for iframe*/
{
position: absolute;
top: 30px;
bottom: 30px;
left: 0px;
right: 0px;
}
#ifrmMainBody
{
width: 100%;
height: 100%;
}
#divFooter
{
position: absolute;
bottom: 0px;
left: 0px;
right: 0px;
height: 30px;
background-color: #926531;
}
/*in master*/
#mainMenu
{
position: absolute;
top: 0px;
left: 0px;
right: 0px;
height: 30px;
background-color: #a9b77c;
}
#navPanel
{
position: absolute;
top: 30px;
left: 0px;
bottom: 0px;
width: 150px;
background-color: #b87c9a;
}
#breadCrumb
{
position: absolute;
top: 30px;
left: 150px;
right: 0px;
height: 20px;
background-color: #ABCDEF;
}
#caption
{
position: absolute;
top: 50px;
left: 150px;
right: 0px;
height: 20px;
background-color: #AB79B8;
}
#subMenu
{
position: absolute;
top: 70px;
left: 150px;
right: 0px;
height: 20px;
background-color: #A7b2E5;
}
#toolBar
{
position: absolute;
top: 90px;
left: 150px;
right: 0px;
height: 20px;
background-color: #E76235;
}
#content
{
position: absolute;
top: 110px;
left: 150px;
right: 0px;
bottom: 0px;
background: #666;
overflow: auto;
}

Resources