40

I have a list of figures containing background images. Something like the following:

<ul>
  <li>
    <figure style="background-image: url(...);"></figure>
  </li>
  <li>
    <figure style="background-image: url(...);"></figure>
  </li>
  <li>
    <figure style="background-image: url(...);"></figure>
  </li>
</ul>

Each of these images has their background-size set to cover and background-attachment set to fixed.

figure {
  width: 100%;
  height: 100%;
  background-size: cover;
  background-attachment: fixed;
}

When each of the figures takes up the entire viewport, this works fine, but if there is an offset of any kind the background-image gets clipped.

As far as I can tell this is by design (https://developer.mozilla.org/en-US/docs/Web/CSS/background-size#Values).

I would like the images to either clip vertically or horizontally but not both, and be centred by the size of the figure itself.

I know there are javascript solutions but is there a way to do this using CSS?

Here is a working example: http://codepen.io/Godwin/pen/KepiJ

4

9 回答 9

63

不幸的是,这只是 CSS 中固定定位如何工作的一种人工制品,在纯 CSS 中无法绕过它——你必须使用 Javascript。

发生这种情况的原因是 和 的background-attachment: fixed组合background-size: cover。当您指定background-attachment: fixed它时,它本质上会导致background-imageposition: fixed像图像一样表现,这意味着它已脱离页面流和定位上下文,并相对于视口而不是它作为背景图像的元素。

因此,无论何时一起使用这些属性,cover都会相对于视口的大小计算该值,而与元素本身的大小无关,这就是为什么当元素与视口大小相同但被裁剪时它会按预期工作的原因当元素小于视口时的意外方式。

为了解决这个问题,您基本上需要使用background-attachment: scroll事件侦听器并将其绑定到scrollJS 中的事件,该事件手动更新background-position相对于窗口滚动的距离以模拟固定定位,但仍background-size: cover相对于容器元素而不是视口进行计算.

于 2014-05-22T15:26:06.740 回答
23

There's a jQuery fix for this: http://jsfiddle.net/QN9cH/1/ I know it's not optimal but at least it works :)

$(window).scroll(function() {
  var scrolledY = $(window).scrollTop();
  $('#container').css('background-position', 'left ' + ((scrolledY)) + 'px');
});
于 2014-11-18T14:17:11.943 回答
3

Nick Noordijk 的回答让我走上了正轨,但我喜欢避免每次滚动事件发生时执行计算的脚本。这是我的版本,它仅在页面加载或屏幕尺寸更改时执行计算:

html:

<div class="fake-img"></div>

CSS:

.fake-img {
    display: block;
    height: 280px;  /* set the height here */
    width: 100%;
    background-image: url('http://example.com/path/to/image.jpg');
    background-repeat: no-repeat;
    background-position: center 68px;
    background-size: auto 50%; /* make a "best guess" here as a default */
    background-attachment: fixed;
    position: relative;
}

jQuery:

$(window).on('resize load orientationchange', function(){
    responsive_calc();
});

var responsive_calc = function(){

    // get the viewport height
    var h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

    // get the element height
    var bannerHeight = $('.fake-img').height();

    // get the integer percentage value difference between them
    var bgHeightPercent = Math.ceil(bannerHeight/h*100);

    // set background-size height to match the element instead of the viewport
    $('.fake-img').css('background-size', 'auto ' + bgHeightPercent + '%');
}

请注意,这实际上仅适用于横向“横幅”图像 -无论您的图像在任一方向上是否多余,使用background-size: auto nn%都不会具有相同的工作优势。background-size: cover

于 2016-08-13T22:44:01.220 回答
3
background: url(<image>) center top no-repeat fixed;
background-size: auto <width size in %>;

没有真正的解决方案。但是,您可以制作图像的尺寸高度auto而不是cover. 并调整元素中的宽度大小(以 % 为单位),直到它咬住边框。

您会看到,如果您调整窗口大小,它不会被剪裁。相反,它将始终保持原始图像大小格式。有了上面的内容,您基本上可以“放大”它,但不会“覆盖”它。

于 2017-09-12T16:18:35.537 回答
2

背景尺寸:封面;属性确实在裁剪图像以使其填充该区域并且没有任何空白空间。

背景尺寸:包含;属性正在确定哪个维度更大并根据该维度进行缩放。因此,如果您有一个 100px x 100px 的块和 200x150px 的背景图像,则将 background-size 设置为 contains 会将图像缩放为 100x75px。但是,在这种情况下,如果元素的纵横比与图像的不同,您将有空白空间。

假设您知道图像的纵横比,您还可以手动控制哪个比例具有优先权。

因此,如果您知道您的图像始终为 100x200 像素,这意味着宽度始终是小尺寸,而高度始终是大尺寸。

现在设置 background-size: 100% auto; 将确保您不会得到空白空间,但最终会被剪裁。如果将其设置为 background-size: auto 100%; 它将确保不会发生剪裁,并且高度永远不会有空白空间(但宽度会)。

如果您确实想要剪裁并将图像居中,请使用 background-position: 50%;。

于 2014-02-17T23:54:30.087 回答
0

另一个非常简单的解决方案是使用vwandvh单位(如果你不知道的话,它在大多数情况下完全可以通过浏览器支持)。例如,不是做,而是background-size: coverbackground-size: auto 100vh

如果您不熟悉vwand vh,它们是视口单位,它们对应于视口宽度和视口高度。这些值对应于视口高度或宽度的百分比。例如,50vw表示视口宽度的 50%。

出于我们的目的,我们可以简单地将背景设置为视口高度的 100%。

这是一个小提琴。

如果您需要适应不同的纵横比,您可以利用纵横比 @media 规则

于 2018-07-24T15:46:31.680 回答
0

单独排列的元素的视差效果示例(不适用于全屏元素):

html:

<div style="background-image: url('/path/to/image.jpg')">Content</div>

CSS:

#element_to_scroll {
    background-repeat: no-repeat;
    background-size: cover; 
    background-position-x: center; 
    background-position-y: 0;   
}

js:

$(window).scroll(function() {
    var realImageWidth = 1280;
    var realImageHeight = 1024;
    var viewportBottom = $(window).scrollTop() + $(window).height();
    $('#element_to_scroll').each(function(){
        var scrollAmountPx = realImageHeight/(realImageWidth/$(this).outerWidth())-$(this).outerHeight();
        var elementOffsetFromBottom = viewportBottom-$(this).offset().top;
        var scrollAreaHeight = $(this).outerHeight() + $(window).height();
        if(elementOffsetFromBottom>0 && elementOffsetFromBottom<scrollAreaHeight) {
            var backgroundPositionOffset = Math.ceil(scrollAmountPx/scrollAreaHeight*elementOffsetFromBottom);
            //$(this).css('background-position-y',"-"+backgroundPositionOffset+"px");
            $(this).clearQueue().animate({'background-position-y':"-"+backgroundPositionOffset+"px"},50);
        }
    });
});
于 2018-05-04T19:15:58.713 回答
0

2018 年 7 月更新:现在有针对此问题的 1 行修复

在阅读这篇文章之前,我遇到了同样的问题,这篇文章告诉我可以将这一行添加到我的 CSS 中以使其工作:

will-change: transform;

有效!

现在我的 CSS 看起来像这样:

.myClass{
    position: relative;
    background: hsla(300, 100%, 90%, 0.1);
    overflow: hidden;
    &::before {
        background-image: url(/img/bg.jpg);
        background-size: cover;
        background-size: cover !important;
        -webkit-background-size: cover !important;
        background-repeat: repeat repeat !important;
        background-attachment: scroll !important;//"fixed" is the desired effect, but mobile browsers find it too "expensive" and disabled it, so use "scroll"
        background-position: 30% 50%;
        @media(min-width: $screen-sm-min){
            background-attachment: fixed !important;
            background-position: 30% 20%;
            will-change: transform;
        }//768
        content: "";
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        opacity: 0.1;
    }
}

它适用于 Windows Chrome、Edge 和 Safari。但不是火狐。

于 2018-07-23T00:21:00.610 回答
-6

我做了一个带有响应背景图像的版本。

.flexslider .slides > li {
  background-position: center center;
  background-repeat: no-repeat;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;
}
#slider,
.alink {
  min-height: 300px
}
.alink {
  display: block
}

http://jsfiddle.net/onigetoc/grpku1gk/

于 2016-11-30T06:26:34.767 回答