-2

I have a fixed header with variant height and the reason for that is the promotion bar that you can see in the preview which is a part of the header.

Now since the rule of the HTML says "It's normal behavior. Give some calculated top margin to your content" so that the content which is hidden under the fixed header will come down.

Now the issue is since I have a variant header height, I can't put a definitive margin-top to the content, and it's because if you close the promotion bar the gap between the header and the content is "too much" and if I don't close the promotion bar which is a default behavior the margin will be completely different.

What are the ways to tackle this issue?

$('div.promotion div.float-right').on('click', function(e) {
    //$(this).closest('div.top-head.fixed-top').hide();
    // or, if you need to remove it
    $('.promotion').remove();
});
.promotion {
  background: #02b875;
  width: 100%;
  float: left;
  height: 38px;
  color: #FFF;
  padding: 8px;
  letter-spacing: 0.2px;
  font-size: 15px;
}

.promotion-code {
  font-weight: 600;
}

.close-promotion {
  cursor: pointer;
}

.top-head {
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
  background: #FFFFFF;
  width: 100%;
  float: left;
  height: 50px;
  padding: 10px;
  position: fixed;
}

.content {
  margin-top: 80px;
  padding: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css">
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">


<div class="fixed-top">
<div class="promotion">
  <div class="container container-responsive">
    Get £20 off on your first trip. Enter <span class="promotion-code">WELCOME20</span> at checkout.
    <div class="close-promotion float-right"><i class="fas fa-times"></i></div>
  </div>
</div>
<div class="top-head">
 <div class="container container-responsive">
 Hello world
   </div>
  </div>
</div>

<div class="content">
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
Content<br>
</div>
Rambo Ron
  • 37
  • 1
  • 9
  • You _know_ the height of that promotion bar, so you can calculate the appropriate margin value for _both_ situations upfront. So all that’s left to do is _change_ the margin that gets applied to the content element, in that very same moment where you remove that promotion bar. Whether you want to do that using `$(…).css()`, or by adding/removing a class, so that the value gets applied directly from your stylesheet … up to you. – misorude Aug 28 '19 at 12:28
  • Any example please via .css()? – Rambo Ron Aug 28 '19 at 12:34
  • I do know how CSS works, but don't know any method of showing conditional thing using CSS. I'm looking for a pure CSS solution no jQuery please. – Rambo Ron Aug 28 '19 at 13:00
  • _“I'm looking for a pure CSS solution”_ - that doesn’t exist. CSS has no way of determining whether that promotion bar element is there or not, _and_ format the content element differently based on that - not with an HTML structure like this. (_Only_ if `.promotion` and `.content` were sibling elements, that would be possible using CSS alone - keywords would be adjacent sibling combinator / general sibling combinator.) – misorude Aug 28 '19 at 13:08
  • 1
    _“I'm looking for a pure CSS solution no jQuery please.”_ - why such an arbitrary requirement, when jQuery is already in use for the part of making the promotion bar disappear? It’s not even as if a pure CSS solution was needed here as a fallback for when no JS might be available - because then your promotion bar just _stays_ to begin with. Sorry, but this is just an absolute nonsense requirement in this particular situation. – misorude Aug 28 '19 at 13:15
  • I understand now, I always try and was also trying to use fewer scripts for faster page load. So I was trying to figure out if there was a way of it achieving it with only CSS as maybe I am not aware of such a way. It's obvious I will have to use the jQuery to sort it out if I end up failing it with CSS. If you notice a guy has shown a way round in the answer below. Please look into it, and let me know if it's the best thing to do? I'm up for all and any suggestions that will fix my issue :) – Rambo Ron Aug 28 '19 at 13:48

2 Answers2

0

You can dynamically calculate the top margin using js. I have used getElementsByClassName but i advise to define Ids and get the element by Id. Example:-

var fixedHeader = 
document.getElementsByClassName("fixed-top")[0];

document.getElementsByClassName("content")[0].style.marginTop = (fixedHeader.offsetTop + fixedHeader.offsetHeight) + "px";
DevLasting
  • 352
  • 1
  • 9
0

It can be done using position:sticky. It is a hybrid of relative and fixed positioning.

I have changed the header div's position to sticky so that .content will be positioned relative to the header while header is fixed at the top of the viewport.

Also I have used flexbox instead of float in the header to align elements.

What is flexbox

$('div.promotion div.float-right').on('click', function(e) {
  //$(this).closest('div.top-head.fixed-top').hide();
  // or, if you need to remove it
  $('.promotion').remove();
});
.header-div {
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  z-index: 10;
}

.promotion {
  background: #02b875;
  height: 38px;
  color: #FFF;
  padding: 8px;
  letter-spacing: 0.2px;
  font-size: 15px;
}

.promotion-code {
  font-weight: 600;
}

.close-promotion {
  cursor: pointer;
}

.top-head {
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
  background: #FFFFFF;
  height: 50px;
  padding: 10px
}

.content {
  padding: 20px;
  
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css">
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">


<div class="header-div">
  <div class="promotion">
    <div class="container container-responsive">
      Get £20 off on your first trip. Enter <span class="promotion-code">WELCOME20</span> at checkout.
      <div class="close-promotion float-right"><i class="fas fa-times"></i></div>
    </div>
  </div>
  <div class="top-head">
    <div class="container container-responsive">
      Hello world
    </div>
  </div>
</div>

<div class="content">
  Content
  <div style="height: 800px; width: 100%;"></div>
  END
</div>

Side note: postion:sticky has limited support in some browsers More info

Soothran
  • 1,233
  • 4
  • 14
  • But then this CSS will be for all clear fixes across the website? I'm using clearfix class at multiple places. – Rambo Ron Aug 28 '19 at 12:57
  • You are free to change the name `clearfix` to `header-clearfix`(_Its just a name_). I 've edited my answer. Also using `flexbox` is a good way to tackle this issue. – Soothran Aug 28 '19 at 13:00
  • I forgot to fix my header in example above. I have revised my sample code, and it doesn't seem to be working anymore. – Rambo Ron Aug 28 '19 at 13:11
  • _“ensures that a div will fully expand to proper height to enclose its floating children”_ - that is not the issue here, when “fixed header” actually means `position: fixed`. A clear fix can not help in that situation, as floating is not the root cause of the issue to begin with. – misorude Aug 28 '19 at 13:13
  • In your examples, it's only working because the header is not fixed. – Rambo Ron Aug 28 '19 at 13:15
  • Yes, I understand, if you read my question above in text is states that the issue is only because of position: fixed and therefore I have to apply margin-top and because it's conditional header height (because the user can close promotion bar) hence I'm looking for a solution via CSS only. I just forgot to add position: fixed in my sample code. So what you've suggested basically is not going to work? Is there any other way in CSS we can achieve what I want? – Rambo Ron Aug 28 '19 at 13:18
  • Does position: sticky do the same job as fixed? – Rambo Ron Aug 28 '19 at 13:56
  • in this case? yes. [more info about position:sticky vs postion:fixed](https://stackoverflow.com/questions/19501919/difference-between-positionsticky-and-positionfixed) – Soothran Aug 28 '19 at 14:11
  • It suggests on the thread you've sent me is position: sticky is not supported in all browsers? Whereas, position:fixed has larger compatibility. – Rambo Ron Aug 28 '19 at 14:26
  • That's right. This solution will work in almost all modern browsers. If you have to support old browsers like IE (and old other browser versions), then a `jquery` solution with `postion:fixed` would be better – Soothran Aug 28 '19 at 14:33
  • So no other CSS solution basically? – Rambo Ron Aug 28 '19 at 14:34
  • There might be. This is the only _pure css_ solution I could provide with the given set of criteria. [JS solution](https://stackoverflow.com/questions/6414384/how-do-i-use-css-to-position-a-fixed-variable-height-header-and-a-scrollable-con) – Soothran Aug 28 '19 at 14:38