How to prevent get over other divs? - javascript

I have a problem...In the following example i don't want that the div who is fixed get over the div with the background red.
Here is the example:
http://jsfiddle.net/HFjU6/3645/
#fixedContainer
{
background-color:#ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px; /*half the width*/
}

Alright, I think I get what the OP wants. He wanted a container that stays fixed on the top of the viewport, but remains confined by a parent. This behaviour is known as a conditional sticky behaviour, and is actually implemented in both Firefox (without vendor prefix) and macOS/iOS Safari (with -webkit- prefix): see position: sticky.
Therefore the easiest (but also the least cross-browser compatible) way is simply to modify your markup, such that the sticky element stays within a parent, and you declare position: sticky on it:
* {
margin: 0;
padding: 0;
}
#fixedContainer {
background-color: #ddd;
position: -webkit-sticky;
position: sticky;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
transform: translate(-50%, 0); /* Negative left margins do not work with sticky */
}
#div1 {
height: 200px;
background-color: #bbb;
}
#div1 .content {
position: relative;
top: -100px; /* Top offset must be manually calculated */
}
#div2 {
height: 500px;
background-color: red;
}
<div id="div1">
<div id="fixedContainer">I am a sticky container that stays within the sticky parent</div>
<div class="content">Sticky parent</div></div>
<div id="div2">Just another element</div>
An alternative would be to use a JS-based solution. In this case, you do not actually have to modify your markup. I have changed the IDs for easier identification of the elements, however.
The gist of the logic is this:
When the scroll position does not exceed the bottom of the parent minus the outer height of the sticky content, then we do not do anything.
When the scroll position exceeds the bottom of the parent minus the outer height of the sticky content, we dynamically calculate the top position of the sticky content so that it remains visually in the parent.
$(function() {
$(window).scroll(function() {
var $c = $('#sticky-container'),
$s = $('#sticky-content'),
$t = $(this); // Short reference to window object
if ($t.scrollTop() > $c.outerHeight() - $s.outerHeight()) {
$s.css('top', $c.offset().top + $c.outerHeight() - $t.scrollTop() - $s.outerHeight());
} else {
$s.css('top', 0);
}
});
});
* {
margin: 0;
padding: 0;
}
div {
height: 500px;
background-color: red;
}
#sticky-container {
background-color: #bbb;
height: 200px;
}
#sticky-content {
background-color: #ddd;
position: fixed;
width: 200px;
height: 100px;
margin-left: -100px;
left: 50%;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sticky-content">Sticky content that stays within the bounds of #div1</div>
<div id="sticky-container">Sticky confinement area</div>
<div>Other content</div>
Old answer before OP clarified the question appropriately:
Just give them the appropriate z-index values. In this case, you want to:
Do not use static positioning. This can be done by using position: relative for the large elements, in conjunction with the originally position: fixed element.
Assign the appropriate stacking order. The grey <div> element to have the lowest z-index, followed by the position fixed element, and then by the red element.
There are some catchalls to stacking though: the stacking context is reset when you traverse up or down the node tree. For example, the example will not work if the elements are not siblings.
Here is a proof-of-concept example, modified from your fiddle so that inline CSS is removed.
* {
margin: 0;
padding: 0;
}
#fixedContainer {
background-color: #ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px;
z-index: 2;
}
#div1 {
height: 200px;
background-color: #bbb;
position: relative;
z-index: 1;
}
#div2 {
height: 500px;
background-color: red;
position: relative;
z-index: 3;
}
<div id="fixedContainer">z-index: 2</div>
<div id="div1">z-index: 1</div>
<div id="div2">z-index: 3</div>

Just give the z-index.
Hope it helps...
http://jsfiddle.net/HFjU6/1/#run
#fixedContainer {
background-color:#ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px; /*half the width*/
z-index: 2;
}
.div-red {
position: relative;
z-index: 5;
}
<div id="fixedContainer"></div>
<div style="height:200px;background-color:#bbb;"></div>
<div style="height:500px;background-color:red;" class="div-red"></div>

Related

div with a large z-index is under the div with a smaller z-index

I had a problem:
Element overlapped element because it has a higher z-index (10 vs 5). Element has the child elements #sub-block-1 & #sub-block-2, and #sub-block-1 had child text #text1 with z-index = 20. But #text1 with z-index = 20 still under with z-index = 10. Why?
Tell me, how can I solve this problem?
The must have a predefined z-index (number, not 'auto', and less than z-index , for example, 5 vs 10).
My example:
https://jsfiddle.net/nynsjv3L/1/
P.S.
The above example is not displayed correctly in jsfiddle - the position of the elements (#sub-block-1 & #sub-block-2) does not work.
body {
background: #00ff00;
}
.screen {
position: absolute;
left: 0px;
top: 0px;
width: 100vw;
height: 100vh;
background: #ffffff;
opacity: 0.75;
z-index: 10;
}
#main-block {
position: absolute;
left: 500px;
top: 200px;
width: 700px;
height: 400px;
border: 2px solid #bb0000;
background: #ff0000;
z-index: 5;
}
.sub-block {
position: absolute;
width: 300px;
height: 150px;
background: #ffffff;
border: 4px solid #000000;
}
#sub-block-1 {
left: 100;
top: 100;
z-index: auto;
}
#sub-block-2 {
left: 275;
top: 175;
z-index: 11;
}
#text1 {
position: absolute;
left: 65px;
top: 55px;
color: #000000;
background: #ffff00;
font-size: 30px;
font-weight: 700;
z-index: 20;
}
#text2 {
position: absolute;
left: 65px;
top: 55px;
color: #00bbbb;
font-size: 30px;
font-weight: 700;
}
<div id='main-block'>
<div class='sub-block' id='sub-block-1'>
<div id='text1'>TEST TEXT</div>
</div>
<div class='sub-block' id='sub-block-2'>
<div id='text2'>NEW TEXT</div>
</div>
</div>
<div class='screen'></div>
The #text is still inside your block, that has a lower index than its sibling. The #text part is still in the same context block of its parent. You could check out the inner workings of z-indexes in this page.
You need to create a new stacking context for the text to appear above the other block. One of the possible ways is to change the opacity of the text to .99, or using the transform attribute. I do not recommend you to do it, though, as it will cause more troubles in the future.
Z-indexes should not be used very often. It is better to organize this inside the HTML itself. You should rethink your work.
#main-block is on the same level as .screen and has a lower z-index. So child elements of #main-block will always be overlapped by .screen and its children.
Whenever you set an element to be position: relative or position: absolute you open up a new z-index-stack for all of its children.
You either have to move the child elements of #main-block some levels up to make them independent or give the #main-block a higher z-index which will also result in overlapping .screen.
Hint: Negative z-index is also possible. And clean up your markup (keyword: single quotes). ;-)

Overlay the Contents of a DIV

I am trying to overlay 2 DIV's in my main parent DIV:
I want to overlay the the second div over on top of the first one. I have a problem overlaying it as I cannot keep it in the middle of the screen.
I have tried this to overlay:
The overlay works fine here, but my container is no longer center when I do this. How can I overlay and keep it center ?
div {
border: 5px solid red;
}
#first {
position: absolute;
z-index: 1;
border-color: orange;
}
#second {
position: absolute;
z-index: 2;
border-color: green;
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
Here is what you need to do (see width of both divs and text-align properties):
You can give them background color to see z-index works perfectly :)
#first {
text-align: center;
height: 300px;
width: 100%;
position: absolute;
z-index: 1;
}
#second {
text-align: center;
height: 300px;
width: 100%;
position: absolute;
z-index: 2;
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
When you position absolute, the positioned element is taken out of the document flow and positioned relative to the next highest parent element that is not the default position, i.e. not position: static;
The following will cause the absolute positioned children to stay within the containing div:
#container {
position: relative;
}
Your container's text is no longer centered because you have removed its children from the document flow. In essence, it has no content and collapses, and therefore, has no width to which to align the text.
One thing you could do is set the container to position: relative and full-width (i.e. width: 100vw), then set its children to width: 100%.
Then the inner divs will take on the width of their parent.
See this working JSFiddle.
#container {
position: relative;
width: 100%;
height: 100px;
background-color: yellow;
display: flex;
justify-content: center;
align-items: center;
}
#first{
position: absolute;
}
#second{
position: absolute;
}
<div id="container" class="container">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>
Your main issue is that the divs will not have any relative width to the parent div.
Therefore the text is still technically "centered" in each corresponding div because they're inheriting text-align: center from the container div.
However, the divs' widths will automatically be as wide as they needs to be (i.e. to fit the text, in this case).
You can remedy this one of two ways:
Force the divs to be centered
Give both divs the following (extra) CSS:
left: 50%;
width: 100%;
margin-left: -50%;
This will literally center them in their parent div.
or
Force the divs to be the same size as their parent
Give both the divs the following (extra) CSS:
top: 0;
bottom: 0;
left: 0;
right: 0;
This sets the divs to span their entire parent's height and width.
In both situations, you might need to make the .container class use position: relative, in order for the child divs to have something to be absolute to.
If you're using Bootstrap, there is no need to worry about this, as .container class already has this applied.
Hope one of these solutions helps you :)
Try this style:
#first,
#second {
left: 50%;
transform: translate(-50%, 0);
}
div {
border: 5px solid red;
}
#first {
position: absolute;
z-index: 1;
border-color: orange;
}
#second {
position: absolute;
z-index: 2;
border-color: green;
}
#first,
#second {
left: 50%;
transform: translate(-50%, 0);
}
<div id="container" class="container text-center">
<div id="first">Hi</div>
<div id="second">Hello</div>
</div>

Fixed positioned element with the same distance to another element when browser window is larger

I am struggling all afternoon to resolve a problem. Maybe this is a common question but I could not find anything similar in here or on Google. I hope you guys can help.
I have a fixed positioned element on the left of the page and I want that the distance between that element and another on the page be always the same when the browser window is larger. How can I do it?
Now, the other element has to be set in percentage while the fixed element can be or not with pixels.
Is there any css calc(), javaScript, jQuery, something you can think of to resolve this?
HTML
<div class="fixed"></div>
<div class="left-element"></div>
CSS
body {
margin: 0;
padding: 0;
border: 1px solid black;
min-height: 2000px;
min-width: 100%;
}
.fixed
{
position: fixed;
top: 0;
left: 0;
height: 200px;
width: 200px;
background-color: blue;
}
.right-element {
width: 25%;
height: 200px;
background-color: yellow;
margin-left: 75%;
}
Here is the Fiddle
I have the same solution as #Calvin Claus but with just a minor css modifcation, no javascript needed
.right-element {
width: calc(100% - 400px);
height: 200px;
background-color: yellow;
margin-left: 400px;
}
fiddle
Update: Similar, but as you asked, the calc on the fixed element.
.fixed {
position: fixed;
top: 0;
left: 0;
height: 200px;
width: calc(75% - 200px);
background-color: blue;
}
.right-element {
width: 25%;
height: 200px;
background-color: yellow;
margin-left: 75%;
}
new fiddle
I came up with a simple jquery solution:
var distanceBetwennElems = 100;
function calcRightElemWidth() {
var rightElemWidth = $(window).width() - ($('.fixed').width() + distanceBetwennElems);
$('.right-element').css("width", rightElemWidth);
}
Just call this when the document is ready and the window is resized.
Also I removed margin and width form the .right-element css, because this is done by js now:
.right-element {
height: 200px;
background-color: yellow;
float: right;
}
https://jsfiddle.net/bjrno78p/2/
You can adjust the width of the left, fixed element, using calc. Here's an example using 500px as the desired distance between the elements, and 25% as the width for the right-element.
.fixed
{
// disired distance = 500px
// right-element width = 25%
width: calc(100vw - 500px - 25%);
}
Your updated fiddle

.toggleClass not toggling a certain class, but is working on all others

So I have a page on my website that has some navigation elements that stick on the page when the user scrolls past a certain point. There are three of them, one on the top, one on the left, and one on the right. HTML and CSS is as follows:
<div id="nav" class="nav">
<!--STUFF CONTAINED IN TOP NAV BAR-->
</div>
<div class="right" id="right">
<!--STUFF CONTAINED IN RIGHT NAV-->
</div>
<div class="left" id="left">
<!--STUFF CONTAINED IN LEFT NAV BAR-->
</div>
.nav {
position: absolute;
top: 108px;
height: 45px;
width: 100%;
left: 0;
right: 0;
}
.nav_sticky {
position: fixed;
top: 0;
height: 45px;
left: 0;
right: 0;
background-image: url(images/backgrounds/stardust_#2X.png);
z-index: 10;
}
.right {
width: 200px;
height: 900px;
position: absolute;
right: 50%;
margin-right: -538px;
top: 153px;
}
.right_sticky {
width: 200px;
height: 900px;
position: fixed;
right: 50%;
margin-right: -538px;
top: 45px;
}
.left {
width: 200px;
height: 900px;
position: absolute;
left: 50%;
margin-left: -538px;
top: 153px;
}
.left_stick {
width: 200px;
height: 900px;
position: fixed;
left: 50%;
margin-left: -538px;
top: 45px;
}
I then use the follow JQuery to cause these elements to stick.
<script>
$(document).ready(function(){
var navPos = $('#nav').offset().top;
$(window).scroll(function () {
var scrollTop = $(this).scrollTop();
if (scrollTop >= navPos) {
var classNamee = $('#nav').attr('class');
console.log(classNamee);
if (classNamee === "nav") {
$("#nav").toggleClass('nav nav_sticky');
$("#right").toggleClass('right right_sticky');
$("#left").toggleClass('left left_stick');
}
}
if (scrollTop <= navPos) {
var className = $('#nav').attr('class');
console.log(className);
if (className === "nav_sticky") {
$("#nav").toggleClass('nav_sticky nav');
$("#right").toggleClass('right_sticky right');
$("#left").toggleClass('left left_stick');
}
}
});
});
</script>
Here's my problem. This works perfectly for the top and right navs, however no matter what I try, the left nav continues to scroll when the others have stopped. I thought it may have been a typo in the css class, but when I looked in the inspector, the .toggleClass function doesn't even change the class on the #left element when it does on the other two. Any ideas as to what could be causing this?
If I copy/paste your sample code as-is to jsFiddle and run it, when you scroll down far enough, it does correctly toggle everything to *_sticky classes, but something about the negative margin-right on the right class element seems to reset the scroll to the top (at least in Chrome) when it flips between .right and .right-stick. When the scroll gets reset, it also reruns your event handeler and changes all the classes back.
Try removing these lines from your CSS and see if the behavior works right (it does in Chrome in a jsFiddle)
.right {
...
/*margin-right: -538px;*/
.right-stick {
...
/*margin-right: -538px;*/

scroll the content inside the div with fixed position using browser/page scroll bar

I have some div's with position:fixed all around the page.
one of that div has little more long content.
my aim is that I want to scroll the content inside that box, using the main browser/page scroll-bar. (its not normal overflow:auto like this)
this is the exact situation
http://s7.postimage.org/d6xl1u9mz/sample.jpg
is any plugin available ?
Without knowledge of your HTML:
<body>
<section id="bodyContent"></section>
<header></header>
<section id="lSide"></section>
<section id="rSide"></section>
</body>
#bodyContent {
box-sizing: border-box;
-moz-box-sizing: border-box;
min-height: 100%;
width: 100%;
padding: 90px 45px 0px 105px;
background-clip: content-box;
background-color: #FFFFFF;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background-image: url(page_background.jpg);
background-attachment: fixed;
}
header, #lSide, #rSide {
position: fixed;
}
header {
top: 0;
width: 100%;
height: 90px;
background-image: url(page_background.jpg);
background-attachment: fixed;
}
#lSide {
left: 0;
top: 0;
height: 100%;
width: 105px;
padding: 90px 0 0 0;
}
#rSide {
right: 0;
top: 0;
height: 100%;
width: 45px;
padding: 90px 0 0 0;
}
This will force the contents of #bodyContent to sit inside the opening between the various border elements, and it will cause any overflow to trigger a scrollbar on the body element as you desire. JSFiddle
Maybe it's possible. I've created a jsFiddle which does the trick. It's not perfect, but you can develope it further... Also this snippet works only with modern browsers, but is easy to fix for older IEs too. Core code below.
JavaScript:
window.onload = function () {
var content = document.getElementById('contentwrapper'),
dimdiv = document.getElementById('scrollingheight'),
wrapHeight = document.getElementById('fixed').offsetHeight,
scroller = function () {
content.style.top = -(document.documentElement.scrollTop || document.body.scrollTop) + 5 + 'px';
return;
};
dimdiv.style.minHeight = (content.scrollHeight - wrapHeight + 2 * 5) + 'px';
window.addEventListener('scroll', scroller, false);
return;
}
CSS:
#fixed {
position: fixed;
min-width: 300px;
min-height: 200px;
max-height: 200px;
background: #fff;
left: 150px;
top: 200px;
overflow-y: hidden;
border: 1px solid #000;
}
#contentwrapper {
max-width: 290px;
position: absolute;
top: 5px;
left: 5px;
}
#scrollingheight {
position: absolute;
top: 100%;
visibility: hidden;
min-width: 1px;
}
HTML:
<div id="scrollingheight"></div>
<div id="fixed">
<div id="contentwrapper">
content
</div>
</div>
Notice, that all content in the body, but #scrollingheight, must be fixed. Constant 5 is related to #contentwrapper's top value.
AFAIK you cannot do that.
At least not without some wicked JS trickery.
Why? cause you cannot force the browser's default scrollbar height (make it smaller) to embrace some content that is inside a totally different area than the html, body (document).
My suggestion is that you build a custom scrollbar, calculate the height of your nice overflow hidden area, add it to the scrollable ratio calculation.

Categories

Resources