简体   繁体   中英

How to set an exact background position based on element's position?

What I am trying to achieve: using the same image, set an elements background-position with jQuery, so they overlaps closest parents background-image . I somehow figured, that $element.property().left needs to be multiplied by something close to 2 (still don't really understand why it's so), but I cannot see any math pattern in it.

If anybody could tell me what exactly comes into an equation, it'd be great help. I imagine there is padding and margin of an element and all the elements up the DOM tree involved, but after lot of combinations I still cannot get there.

It might seem that the best way to get desired effect is just to set background: transparent; , but it is not the case ; I need it for further usage of filter CSS property on the element's background image.

There are inline styles in HTML added for testing; also, I created jsfiddle .

 $.fn.filteredImg= function() { var $this = $(this) $this.each(function(index, card) { var $card = $(card); var img = $card.data("img"); var $parent = $card.parentsUntil("[data-img='" + img + "']").last().parent(); var $effect = $card.children(".filtered-effect"); var pos = $card.position(); $parent.css({ backgroundImage: "url(" + img + ")", backgroundRepeat: "no-repeat" }); $effect.css({ backgroundImage: "url(" + img + ")", backgroundPosition: -2 * Math.ceil(pos.left) + "px " + -Math.round(pos.top) + "px" }); }) } $(".card-filtered-img").filteredImg(); 
 .card-filtered-img { width: 80%; min-height: 500px; margin-left: 77px; margin-top: 17px; position: relative; } .card-filtered-img > * { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .card-filtered-img .filtered-effect { z-index: 99; } .card-filtered-img .card-content { background: rgba(34, 34, 34, 0.35); z-index: 100; } 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg"> <div class="container" style="margin-top:30px"> <div class="row" style="padding:30px"> <div class="col"> <div class="card-filtered-img" data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg"> <div class="filtered-effect"></div> <div class="card-content"></div> </div> <div class="card-filtered-img" data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg"> <div class="filtered-effect"></div> <div class="card-content"></div> </div> </div> </div> </div> 

Here is the solution base on offset instead of position (and I simplified the code):

 $.fn.filteredImg= function() { var $this = $(this); $this.each(function(index, card) { var $card = $(card); var $effect = $card.children(".filtered-effect"); var $parent = $(card).parents(".parent").first(); var img = $parent.data("img"); var cardPos = $card.offset(); $parent.css({ backgroundImage: "url(" + img + ")", backgroundRepeat: "no-repeat" }); $effect.css({ backgroundImage: "url(" + img + ")", backgroundPosition: -cardPos.left + "px " + -cardPos.top + "px" }); }) } $(".card-filtered-img").filteredImg(); 
 .card-filtered-img { width: 80%; min-height: 500px; margin-left: 77px; margin-top: 17px; position: relative; } .card-filtered-img > * { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .card-filtered-img .filtered-effect { z-index: 99; } .card-filtered-img .card-content { background: rgba(34, 34, 34, 0.35); z-index: 100; } 
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="parent" data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg"> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="card-filtered-img"> <div class="filtered-effect"></div> <div class="card-content"></div> </div> </div> </div> <div class="row"> <div class="col-md-12"> <div class="card-filtered-img"> <div class="filtered-effect"></div> <div class="card-content"></div> </div> </div> </div> </div> 

Since/If you use the full viewport, you can use viewport units to position and size the inner card 's and drop the script all together.

This also scales when you resize and will give you a performance boost since you don't need a script to watch for resize and redraw.

Note, for this demo I ran this without bootstrap , as I didn't want to add compensations for its media query's etc.

Updated fiddle

 html, body { margin: 0; overflow-x: hidden; } .outer { height: 1080px; width: 100vw; } .card-acrylic { top: 20px; width: 80vw; margin-left: 10vw; min-height: 500px; position: relative; background-position: left -10vw top -20px; } .card-acrylic + .card-acrylic { top: 40px; background-position: left -10vw top -540px; } .card-acrylic > * { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .card-acrylic .acrylic-effect { z-index: 99; } .card-acrylic .card-content { background: rgba(34, 34, 34, 0.35); z-index: 100; } 
 <div class="outer" style="background-image: url(http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg)"> <div class="card-acrylic" style="background-image: url(http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg)"> <div class="acrylic-effect"></div> <div class="card-content"></div> </div> <div class="card-acrylic" style="background-image: url(http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg)"> <div class="acrylic-effect"></div> <div class="card-content"></div> </div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM