Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed position background image inside div

I want to make background of a div fixed so switching div will gave an effect of switching images like on phone screen. It is like worsen version of this: https://www.android.com/versions/nougat-7-0/

Fiddle link.

I am trying in this way:

.main {
  min-height: 1000px;
}

.col1 {
  width: 29.9%;
  min-height: 800px;
  display: inline-block;
  float: left;
}

.col2 {
  width: 70%;
  min-height: 800px;
  display: inline-block;
}

.row1 .col1 {
  background: rgba(238, 238, 34, 0.3) url("https://icons.iconarchive.com/icons/graphicloads/100-flat-2/256/24-hours-phone-icon.png") !important;
  background-position: left !important;
  background-repeat: no-repeat !important;
  background-size: contain !important;
  background-attachment: fixed !important;
}

.row2 .col1 {
  background: rgba(238, 238, 34, 0.3) url("https://icons.iconarchive.com/icons/graphicloads/100-flat-2/256/abs-icon.png") !important;
  background-position: left !important;
  background-repeat: no-repeat !important;
  background-size: contain !important;
  background-attachment: fixed !important;
}

.row3 .col1 {
  background: rgba(238, 238, 34, 0.3) url("https://icons.iconarchive.com/icons/graphicloads/100-flat-2/256/arrow-down-icon.png") !important;
  background-position: left !important;
  background-repeat: no-repeat !important;
  background-size: contain !important;
  background-attachment: fixed !important;
}
<div class="main">
  <div class="row1">
    <div class="col1">
      Col1
    </div>
    <div class="col2">
      Col2
    </div>
  </div>
  <div class="row2">
    <div class="col1">
      Col1
    </div>
    <div class="col2">
      Col2
    </div>
  </div>
  <div class="row3">
    <div class="col1">
      Col1
    </div>
    <div class="col2">
      Col2
    </div>
  </div>
</div>

But there is no luck since picture is always bigger than div and not inside div as i need and even more problem is that when browser size is changing a background position is changing too.

I know because of background attachment fixed, so it is looking a hole viewport and not a div only, but is there any workaround to achieve this?

So goal is to have background image nicely on center BUT fixed position inside this mother div, so when scrolling an switching effect will be given. When changing browser viewport picture is always the same size at the center of mother div.


I know about scroll magic, but i just want something more "natural" trough CSS or might minimum JS code.

like image 549
Danijel Avatar asked Sep 11 '17 07:09

Danijel


2 Answers

After some trying I came out with this one, BUT it's a JS solution, still will be very happy if anyone crack it with pure CSS.

Fiddle link https://jsfiddle.net/w4hz4cqf/31/

Changed CSS code a bit:

    .main
    {
      min-height: 1000px;
      width: 500px;
      margin: 0 auto;

    }

    .col1
    {
      width: 150px;
      min-height: 800px;
      display: inline-block;
      float: left;
    }

    .col2
    {
      width: 70%;
      min-height: 800px;
      display: inline-block;
    }

    .row1 .col1
    {
      background: rgba(238,238,34,0.3) url("https://icons.iconarchive.com/icons/graphicloads/100-flat-2/256/24-hours-phone-icon.png") !important;
        //background-position: left !important;
        background-repeat: no-repeat !important;
        background-size: 100px 100px !important;
        background-attachment: fixed !important;
    }

    .row2 .col1
    {
        background: rgba(238,238,34,0.3) url("https://icons.iconarchive.com/icons/graphicloads/100-flat-2/256/abs-icon.png") !important;
        background-position: left !important;
        background-repeat: no-repeat !important;
        background-size: 100px 100px !important;
        background-attachment: fixed !important;
    }

    .row3 .col1
    {
        background: rgba(238,238,34,0.3) url("https://icons.iconarchive.com/icons/graphicloads/100-flat-2/256/arrow-down-icon.png") !important;
        background-position: left !important;
        background-repeat: no-repeat !important;
        background-size: 100px 100px !important;
        background-attachment: fixed !important;
    }

Added JS Code:

    jQuery(document).ready(function(){
      backgroundImageSize = 100;

      elem = jQuery(".row1 .col1, .row2 .col1, .row3 .col1"); 
      for(ind = 0; ind < 3; ind++) {
        elem[ind].getBoundingClientRect();

          elem[ind].style.setProperty('background-position', (elem[ind].getBoundingClientRect().left + jQuery(".col1").width() / 2 - (backgroundImageSize/2))+'px center', 'important');
      }

      var width = $(window).width();
      $(window).on('resize', function(){
         if($(this).width() != width){
            width = $(this).width();
            elem = jQuery(".row1 .col1, .row2 .col1, .row3 .col1"); 

            for(ind = 0; ind < 3; ind++) {
              elem[ind].getBoundingClientRect();
              elem[ind].style.setProperty('background-position', (elem[ind].getBoundingClientRect().left + jQuery(".col1").width() / 2 - (backgroundImageSize/2))+'px center', 'important');
            }
         }
      });
    });
like image 80
Danijel Avatar answered Sep 30 '22 05:09

Danijel


Unfortunately this is simply an artifact of how fixed positioning works in CSS and there is no way around it in pure CSS - you have to use Javascript.

The reason this happens is due to the combination of background-attachment: fixed and background-size: cover. When you specify background-attachment: fixed it essentially causes the background-image to behave as if it were a position: fixed image, meaning that it's taken out of the page flow and positioning context and becomes relative to the viewport rather than the element it's the background image of.

To get around this you basically need to use background-attachment: scroll and bind an event listener to the scroll event in JS that manually updates the background-position relative to how far the window has been scrolled in order to simulate fixed positioning but still calculate background-size: cover relative to the container element rather than the viewport.

like image 30
Anmol Sandal Avatar answered Sep 30 '22 06:09

Anmol Sandal