Reputation: 11281
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>
Upvotes: 0
Views: 405
Reputation: 87191
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.
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>
Upvotes: 0
Reputation: 4919
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>
Upvotes: 1