2

I'm new in css. I confused in position. There is a simple example.

https://jsfiddle.net/4t8zn9yo/1/

$(document).ready(function() {
 $('.content').scroll(function() {
   if ($(this).scrollTop() > 0) {
     if (!$('.topline').hasClass('long'))
       $('.topline').addClass('long')
    } else {
     if ($('.topline').hasClass('long'))
       $('.topline').removeClass('long')
    }
  });
});
.header {
  position: relative;
  height: 65px;
  background: brown;
  overflow-y: hidden;
  overflow-x: hidden;
}
  
.topline {
  position: absolute;
  top: 0px;
  width: 100vw;
  height: 5px;
  background: blue;
  transition: 0.2s;
}

.topline.long {
  height: 65px;
  transition: 0.2s;
}

.topbar {
  display: flex;
  justify-content: center;
  position: relative;
  margin-top: 10px;
}

.topbar div {
  flex: 1;
  color: white;
}

.content {
  height: calc(100vh - 65px);
  overflow-y: auto;
  overflow-x: hidden;
}

.content-parta {
  height: 800px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class='header'>
 <div class='topline'>
  
  </div>
  <div class='topbar'>
    <div>test1</div>
    <div>test2</div>
    <div>test3</div>
    <div>test4</div>
  </div>
 
</div>
<div class='content'>
  <div class='content-parta'>
    
  </div>
</div>

When scroll event trigger, topline class is higher than topbar class. I have no idea why the son of topbar class is higher than topline class.

When I move the topline class after the topbar class, it is the highest.

I want to know why.

Jeff
  • 23
  • 2
  • 1
    It's because of the [stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context). If you want top line above top bar without moving them, then use a z-index – Pete Sep 05 '19 at 07:46
  • @Pete Thanks! It help! – Jeff Sep 05 '19 at 08:47

2 Answers2

0

HTML thinks that it is now behind. Think of it as a 3 dimensional environment. You can use z-index. This way you can control how the appearance works. You can check this out.

Ozgur O.
  • 97
  • 9
0

If you refer to the specification and the painting order:

  1. All positioned, opacity or transform descendants, in tree order that fall into the following categories:
  1. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.

Both elements are positionned with the same properties (z-index:auto is the important one) so the tree order will decide which one will be on the top. In your actual code topbar is on the top. If you switch the HTML order you will have it on the bottom:

$(document).ready(function() {
    $('.content').scroll(function() {
    if ($(this).scrollTop() > 0) {
        if (!$('.topline').hasClass('long'))
        $('.topline').addClass('long')
    } else {
        if ($('.topline').hasClass('long'))
        $('.topline').removeClass('long')
    }
  });
});
.header {
  position: relative;
  height: 65px;
  background: brown;
  overflow-y: hidden;
  overflow-x: hidden;
}
  
.topline {
  position: absolute;
  top: 0px;
  width: 100vw;
  height: 5px;
  background: blue;
  transition: 0.2s;
}

.topline.long {
  height: 65px;
  transition: 0.2s;
}

.topbar {
  display: flex;
  justify-content: center;
  position: relative;
  margin-top: 10px;
  background:red;
}

.topbar div {
  flex: 1;
  color: white;
}

.content {
  height: calc(100vh - 65px);
  overflow-y: auto;
  overflow-x: hidden;
}

.content-parta {
  height: 800px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class='header'>
 <div class='topline'>
  
  </div>
  <div class='topbar'>
    <div>test1</div>
    <div>test2</div>
    <div>test3</div>
    <div>test4</div>
  </div>
 
</div>
<div class='content'>
  <div class='content-parta'>
    
  </div>
</div>

If you remove the position from one element, whataver the tree order the other positionned element will always be on the top.

$(document).ready(function() {
    $('.content').scroll(function() {
    if ($(this).scrollTop() > 0) {
        if (!$('.topline').hasClass('long'))
        $('.topline').addClass('long')
    } else {
        if ($('.topline').hasClass('long'))
        $('.topline').removeClass('long')
    }
  });
});
.header {
  position: relative;
  height: 65px;
  background: brown;
  overflow-y: hidden;
  overflow-x: hidden;
}
  
.topline {
  position: absolute;
  top: 0px;
  width: 100vw;
  height: 5px;
  background: blue;
  transition: 0.2s;
}

.topline.long {
  height: 65px;
  transition: 0.2s;
}

.topbar {
  display: flex;
  justify-content: center;
  margin-top: 10px;
  background:red;
}

.topbar div {
  flex: 1;
  color: white;
}

.content {
  height: calc(100vh - 65px);
  overflow-y: auto;
  overflow-x: hidden;
}

.content-parta {
  height: 800px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class='header'>
 <div class='topline'>
  
  </div>
  <div class='topbar'>
    <div>test1</div>
    <div>test2</div>
    <div>test3</div>
    <div>test4</div>
  </div>
 
</div>
<div class='content'>
  <div class='content-parta'>
    
  </div>
</div>

Related:

Why can't an element with a z-index value cover its child?

Why does position:relative; appear to change the z-index?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415