裁剪顶部

Avatar of Parker Bennett
Parker Bennett

DigitalOcean 提供适用于旅程每个阶段的云产品。立即开始使用 $200 免费信用额度!

以下是 Parker Bennett 的客座文章,他探讨了处理灵活和响应式图像行为的不同方法。

有时你希望一张图像在调整大小时可以响应式地调整大小,但限制其高度,并在图像变宽时进行裁剪。在本篇文章中,我们将探讨三种具有不同权衡的选项。

幸福的夫妻,位于正中央:background-position: center bottom

选项一:background-image

在 CodePen 上编辑

在这里,我们使用一个带有 background-image 的 div 来替代 <img>,并使用 CSS3 的新特性 background-size: cover 来使其按比例缩放。作为奖励,我们可以使用 background-position 很容易地从顶部、中心或底部进行裁剪。

一个潜在的问题是,我们需要为 div 指定一个高度才能显示它。这会赋予它一个固定高度,而这个高度不会按比例缩放(至少在没有 CSS 媒体查询的情况下不会)。当它变得足够窄时,两侧将开始裁剪(这可能是可取的,这取决于情况)。

此外,使用 caniuse.com 进行快速检查表明,这在 IE8 中会显着失败(显示全尺寸图像),但感谢 Louis-Rémi Babé,有一个 background-size 填充 解决方法(尽管它确实需要一个相对位置或固定位置,以及一个 z-index)。IE8 还需要一个 CSS 媒体查询的填充。有 几个 选项

.bg-image {
  /* image specified in separate class below */
  height: 240px;
  width: 100%; 
}

.bg-image-wedding {
  background-image: url(img/photo-wedding_1200x800.jpg);

  /* lt ie8 */
  -ms-background-position-x: center;
  -ms-background-position-y: bottom;
  background-position: center bottom;

  /* scale bg image proportionately */
  background-size: cover;
    
  /* ie8 workaround - http://louisremi.github.io/background-size-polyfill/ */
  -ms-behavior: url(/backgroundsize.min.htc);
  /* prevent scaling past src width (or not) */
  /* max-width: 1200px; */
}

/* example media queries */
@media only screen and (min-width : 768px) {
  .bg-image { height: 320px; }
}

@media only screen and (min-width : 1200px) {
  .bg-image { height: 400px; }
}
那是中间的我:background-position: center center

需要注意的是,background-size: cover 会很容易地将图像放大到超过源图像的原始大小(或者不会,如果你设置了一个 max-width)。*

尽管如此,使用 background-image 还是有一些缺点。它不像 img 那样语义化或模块化,因此维护起来没有那么直接。你似乎只能使用固定高度或繁琐的 CSS 媒体查询。此外,用户无法轻松保存图像(有时这是可取的)。

选项二:img 带有调整

在 CodePen 上编辑

在这里,我们使用一个带有 max-width 设置为包含元素百分比的 img,使其可以响应式地缩放,然后将其包裹在一个带有 overflow: hidden 和指定高度或 max-height 的 div 中。

wedding

当你调整大小超过 700 像素时,新娘就会消失。
.crop-height {
  /* max-width: 1200px; /* img src width (if known) */
  max-height: 320px;
  overflow: hidden; 
}

img.scale {
  /* corrects inline gap in enclosing div */
  display: block;
  max-width: 100%;
  /* just in case, to force correct aspect ratio */
  height: auto !important;
  width: auto\9; /* ie8+9 */
  /* lt ie8 */
  -ms-interpolation-mode: bicubic; 
}

如你所见,图像的底部现在会在图像变宽时被裁剪。但是,如果你想从顶部裁剪呢?令人惊讶的是,你可以做到——使用 CSS3 的 transform:rotate(),我们将 "flip" 类添加到 img.scalediv.crop-height 中——将 img 翻转过来。

wedding

幸福的夫妻回来了!(除非你使用的是 IE8 或更早版本)。
/* apply to both img.scale and div.crop-height */
.flip {
  -webkit-transform: rotate(180deg);
  -moz-transform:    rotate(180deg);
  -ms-transform:     rotate(180deg);
  -o-transform:      rotate(180deg);
  transform:         rotate(180deg);
  /* needed? not sure */
  zoom: 1;
}

img.flip {
  /* if native or declared width of img.scale
     is less than div.crop-height, this will
     flipped img left */
  float: right;
  /* add clearfix if needed */ 
}

新颖,但仅限于顶部裁剪。而且,如你所料,这 在 IE8 中也不起作用——可能不会显着失败(它只会像以前一样从底部裁剪)。坏消息是,我还没有找到任何 填充 选项 有效,因为它们需要指定高度和宽度。

选项三:混合方法

在 CodePen 上编辑

如果我们可以同时拥有指定 img 的优势(例如,使用 max-height 使我们在低于一定高度时获得按比例的垂直缩放),以及 background-image 提供的灵活裁剪和 IE8 填充支持呢?我们可以!

img 的 visibility: hidden,background-image 的 background-position: center center

诀窍是使响应式缩放的 img 不可见。使用 visibility: hidden 它会保留布局,因此我们会在它的后面看到 background-image。(由于它使用的是同一个图像源,因此它不应该需要下载两次)。如果你想让用户可以轻松访问,你可以使用 opacity: 0 代替。现在用户可以拖动图像或右键单击保存。(不透明度和 background-size 需要一些额外的 IE8 解决方法)。

wedding

opacity: 0。一个可以拖动或右键单击保存的 background-image。在 IE8 中有效(借助帮助)。

另一个想法是使用一个压缩程度更高的代理 img,并使用 CSS 媒体查询根据需要提供更高分辨率的 background-image。这个 img 甚至可以是一个按比例缩小的尺寸(例如,与你的 max-height 相匹配),或带有水印。查看这篇文章 关于媒体查询的 CSS-Tricks 文章,以及这个有用的 用于 Sass 的分辨率 mixin

wedding

在这里,一个 70 KB 的半尺寸 img 用于为更高分辨率的 background-image 保留空间。
.crop-height {
    /* max-width: 1200px; /* img src width (if known) */
    max-height: 320px;
    overflow: hidden; }

.bg-image-wedding {
    /* for small devices */
    background-image: url(img/photo-wedding_1200x800.jpg);
    /* lt ie8 */
    -ms-background-position-x: center;
    -ms-background-position-y: bottom;
    background-position: center bottom;
    /* scale bg image proportionately */
    background-size: cover;
    /* ie8 workaround - http://louisremi.github.io/background-size-polyfill/ */
    -ms-behavior: url(/backgroundsize.min.htc);
    */ prevent scaling past src width (or not) */
    /* max-width: 1200px; */ }

.invisible {
    visibility: hidden; }

.transparent {
    /* trigger hasLayout for IE filters below */
    zoom: 1;
    /* 0 opacity in filters still displays layout */
    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
    filter: alpha(opacity=10);
    opacity: 0; }

/* example media query for smaller non-retina devices */
@media
    only screen and (max-device-width : 600px) and (-webkit-max-device-pixel-ratio: 1),
    only screen and (max-device-width : 600px) and (        max-device-pixel-ratio: 1) {
      
     .bg-image-wedding {
       background-image: url(img/photo-wedding_600x400.jpg); 
     }
}

/* example media query for retina ipad and up */
@media
    only screen and (min-device-width : 768px) and (-webkit-min-device-pixel-ratio: 1.5),
    only screen and (min-device-width : 768px) and (        min-device-pixel-ratio: 1.5) {

      .bg-image-wedding {
        background-image: url(img/[email protected]); 
      }
}

总结

在 CSS3 的 object-fit 支持到来之前,这可能还需要一段时间,这个混合选项在我看来是最好的方法。尽管如此,拥有选择总归是好的。我希望你能从我这次过于详尽的探索中有所收获。你可以查看源代码了解更多信息(选项 ),或者 在这里下载示例文件。如果你有任何问题、评论或更正,请给我留言:parker@parkerbennett.com.


* 如果你想让 img 像 background-image 一样放大,你可以做到。你只需要 "预放大" 它,在 img 元素本身添加一个按比例更大的宽度和高度:<img width="2400px" height="1600px" src="img/photo-wedding_1200x800.jpg /> (在 CodePen 上编辑).