Hassan Baig
Hassan Baig

Reputation: 15834

Positioning elements with position:fixed side-by-side each other

For a web application meant for mobile browsers, I want to integrate this simple yet elegant preloader. It's going to reside on top of a translucent overlay. It's also going to have some words on top of it (e.g. "Please wait...", or "Hold on a minute..." etc).

I tried integrating all that. The result is below (run the snippet). It has 3 distinct problems (can you help me solve them all):

1) I haven't been able to position the preloader + it's text on top of the translucent overlay (although I've used a high z-index).

2) Moreover, the preloader graphic is getting skewed in accordance with the length of the sentence on top of it. I want it to be independent of that.

3) Lastly, they're not positioned in the exact middle (vertically speaking).

body{background:#ECF0F1}

.parent{
  position:fixed;
  z-index:1;
  top:50%;
  left:50%;
  transform:translate(-50%, -50%);
}

.caption{
  margin-bottom:1em;
  color:gray;
  position:relative;
  z-index:10;
}

.load{
  width:50px;
  height:50px;
  position:relative;
  z-index:10;
  
}
.load hr{border:0;margin:0;width:40%;height:40%;position:fixed;border-radius:50%;animation:spin 2s ease infinite}

.load :first-child{background:#19A68C;animation-delay:-1.5s}
.load :nth-child(2){background:#F63D3A;animation-delay:-1s}
.load :nth-child(3){background:#FDA543;animation-delay:-0.5s}
.load :last-child{background:#193B48}

@keyframes spin{
  0%,100%{transform:translate(0)}
  25%{transform:translate(160%)}
  50%{transform:translate(160%, 160%)}
  75%{transform:translate(0, 160%)}
}

.overlay{
  position:fixed;
  width:100%;
  height:100%;
  top:0;
  left:0;
  opacity:0.6;
  z-index:100;
  background-color:#FFFFFF;
}

body {

   background: #E8F5E9;
   background: repeating-linear-gradient(
  to right,
 #FAFAFA,
  #FAFAFA 50px,
  #E8F5E9 50px,
  #E8F5E9 100px
);
 }
<body>
  <div class="overlay">
    <div class="parent">
      <div class="caption">Lorem ipsum dolor sit amet ...</div>
      <div class="load">
        <hr><hr><hr><hr>
      </div>
    </div>
  </div>
<body>

Note: I'm hoping for pure CSS solutions, no JS involvement. I'd also want to avoid flex-box, and go for something universal (in a backward compatibility sense). E.g. flex-box support dwindles in older versions of Android browser (according to caniuse.com). I want to respect those versions too, hence it's best to stick to well-supported CSS 2.1 properties.

Upvotes: 2

Views: 29

Answers (2)

Temani Afif
Temani Afif

Reputation: 273512

The issue is with the hr element they are placed fixed and they should be absolute to keep their relation with parent container. And then simply add margin:auto to load to center them.

And since parent and overlay elements are both fixed position you can separate them to be able to correctly use z-index and avoid the opacity being applied of overlay:

body {
  background: #ECF0F1
}

.parent {
  position: fixed;
  z-index: 1000;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.caption {
  margin-bottom: 1em;
  color: gray;
  position: relative;
  z-index: 10;
}

.load {
  width: 50px;
  height: 50px;
  position: relative;
  z-index: 10;
  margin: auto;
}

.load hr {
  border: 0;
  margin: 0;
  width: 40%;
  height: 40%;
  position: absolute;
  border-radius: 50%;
  animation: spin 2s ease infinite
}

.load :first-child {
  background: #19A68C;
  animation-delay: -1.5s
}

.load :nth-child(2) {
  background: #F63D3A;
  animation-delay: -1s
}

.load :nth-child(3) {
  background: #FDA543;
  animation-delay: -0.5s
}

.load :last-child {
  background: #193B48
}

@keyframes spin {
  0%,
  100% {
    transform: translate(0)
  }
  25% {
    transform: translate(160%)
  }
  50% {
    transform: translate(160%, 160%)
  }
  75% {
    transform: translate(0, 160%)
  }
}

.overlay {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  opacity: 0.6;
  z-index: 100;
  background-color: #FFFFFF;
}

body {
  background: #E8F5E9;
  background: repeating-linear-gradient( to right, #FAFAFA, #FAFAFA 50px, #E8F5E9 50px, #E8F5E9 100px);
}
<div class="overlay">
</div>
<div class="parent">
  <div class="caption">Lorem ipsum dolor sit amet ...</div>
  <div class="load">
    <hr>
    <hr>
    <hr>
    <hr>
  </div>
</div>

Upvotes: 1

Facundo Corradini
Facundo Corradini

Reputation: 3923

The preloader is a child of the overlay, therefore it will have the parent opacity, no way to avoid that but setting it outside the overlay, maybe as a sibling, and adjust the overlay with a negative z-index

As for the sizing, the he are ignoring the parent size as they are set to position:fixed, should be absolute

body {
  background: #ECF0F1
}

.parent {
  position: fixed;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.caption {
  margin-bottom: 1em;
  color: gray;
  position: relative;
  z-index: 10;
}

.load {
  width: 50px;
  height: 50px;
  position: relative;
  z-index: 10;
  margin: auto;
}

.load hr {
  border: 0;
  margin: 0;
  width: 40%;
  height: 40%;
  position: absolute;
  border-radius: 50%;
  animation: spin 2s ease infinite
}

.load :first-child {
  background: #19A68C;
  animation-delay: -1.5s
}

.load :nth-child(2) {
  background: #F63D3A;
  animation-delay: -1s
}

.load :nth-child(3) {
  background: #FDA543;
  animation-delay: -0.5s
}

.load :last-child {
  background: #193B48
}

@keyframes spin {
  0%,
  100% {
    transform: translate(0)
  }
  25% {
    transform: translate(160%)
  }
  50% {
    transform: translate(160%, 160%)
  }
  75% {
    transform: translate(0, 160%)
  }
}

.overlay {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  opacity: 0.6;
  z-index: -10;
  background-color: #FFFFFF;
}

body {
  background: #E8F5E9;
  background: repeating-linear-gradient( to right, #FAFAFA, #FAFAFA 50px, #E8F5E9 50px, #E8F5E9 100px);
}
<div class="overlay">
</div>

<div class="parent">
    <div class="caption">Lorem ipsum dolor sit amet ...</div>
    <div class="load">
      <hr>
      <hr>
      <hr>
      <hr>
    </div>
  </div>

Upvotes: 1

Related Questions