How can I remove the non-visible part of `clip-path`?

给你一囗甜甜゛ 提交于 2019-12-11 04:24:20

问题


I would like to cut out images that vary in size at a height of 50% each.

So I thought about using the inset method of the clip-path property. But, in this property, the cut out space remains as height.

.container {
  display: flex;
  align-items: start;
}

.img {
  flex: 1;
  background: #900;
}

.img+.img {
  margin-left: 5px;
}

img {
  max-width: 100%;
  width: 100%;
  clip-path: inset(0 0 45% 0);
}
<div class="container">
  <div class="img">
    <img src="https://via.placeholder.com/300x550/009/fff.png" alt>
  </div>
  <div class="img">
    <img src="https://via.placeholder.com/200x200/090/fff.png" alt>
  </div>
  <div class="img">
    <img src="https://via.placeholder.com/600x150/09f/fff.png" alt>
  </div>
</div>

So I used overflow: hidden andheight to edit the source code as follows:

.container {
  display: flex;
  align-items: start;
  height: 100vh;
}

.img {
  flex: 1;
  background: #900;
  height: 45%;
  overflow: hidden;
}

.img+.img {
  margin-left: 5px;
}

img {
  max-width: 100%;
  width: 100%;
}
<div class="container">
  <div class="img">
    <img src="https://via.placeholder.com/300x550/009/fff.png" alt>
  </div>
  <div class="img">
    <img src="https://via.placeholder.com/200x200/090/fff.png" alt>
  </div>
  <div class="img">
    <img src="https://via.placeholder.com/600x150/09f/fff.png" alt>
  </div>
</div>

But, it will be 45% of the height of the parent container, not 45% of the height of the image.

Why is this behavior? And how do I cut out 50% of the height of each image and get rid of the extra space?


回答1:


Percentage height is relative to the parent element and in this case you are facing a complex behavior where the 45% is the height of the tallest image that is defining the parent height.

One idea to obtain what you want is to consider scaling where you up scale the image twice and you down scale the container twice:

.container {
  display: flex;
  align-items: start;
  height: 100vh;
}

.img {
  flex: 1;
  background: #900;
  overflow: hidden;
  transform:scaleY(0.5);
  transform-origin:top;
}

.img+.img {
  margin-left: 5px;
}

img {
  max-width: 100%;
  width: 100%;
  transform:scaleY(2);
  transform-origin:top;
}
<div class="container">
  <div class="img">
    <img src="https://via.placeholder.com/300x550/009/fff.png" alt>
  </div>
  <div class="img">
    <img src="https://via.placeholder.com/200x200/090/fff.png" alt>
  </div>
  <div class="img">
    <img src="https://via.placeholder.com/600x150/09f/fff.png" alt>
  </div>
</div>



回答2:


Interesting challenge.

Below is a method which has the appearance of cropping each image to only its top height, but it requires that the frames containing each image still be the full height.

Note that I've rename what you called div.imgs to div.frames for clarity.

.container {
  display: flex;
  align-items: start;
  height: 100vh;
}

.frame {
  flex: 1;
  background: lightgrey; /* set transparent to make frames invisible */
  position: relative;
}

img {
  display: block; /* default is inline-block, which adds extra space */
}

.frame + .frame {
  margin-left: 5px;
}

.frame > img {
  /* this image expands the .frame to fit full image size */
  height: auto;
  width: 100%;
  visibility: hidden;
}

.cropper {
  /* with parent .frame set to full image hight, 50% of .frame height is 50% of image hight */
  position: absolute;
  height: 50%;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
}

.cropper img {
  /* inside the cropper, display the normal image—it'll overflow at 50% of its height */
  width: 100%;
}
<div class="container">
  <div class="frame">
    <img src="https://via.placeholder.com/300x550/009/fff.png" alt>
    <div class="cropper">
      <img src="https://via.placeholder.com/300x550/009/fff.png" alt>
    </div>
  </div>
  <div class="frame">
    <img src="https://via.placeholder.com/200x200/090/fff.png" alt>
    <div class="cropper">
      <img src="https://via.placeholder.com/200x200/090/fff.png" alt>
    </div>
  </div>
  <div class="frame">
    <img src="https://via.placeholder.com/600x150/09f/fff.png" alt>
    <div class="cropper">
      <img src="https://via.placeholder.com/600x150/09f/fff.png" alt>
    </div>
  </div>
</div>

It works by placing a full-height, invisible image within each div.frame. This "expands" each div.frame from the inside to match the full height of the image. Each div.frame then also contains an absolultey-positioned div.cropper, set to 50% of its parent container's height. Because our invisible image set our div.frame to the height of the image, this is 50% of the image's height, even as it scales. Finally, that .cropper contains our image again. Because .cropper is set to overflow: hidden, only the top 50% of the image is shown.

I've colored the .frames grey to illustrate what's going on. If you don't want the .frames to be visible, you can simply set their background-color: transparent (or don't specifiy a background-colortransparent is the default).

You may be able to cut back on <img> elements and achieve the same effect using background-image, but I've yet to twist this method just right to find way that doesn't require the .frames to remain full height while their contents are "chopped".



来源:https://stackoverflow.com/questions/55304008/how-can-i-remove-the-non-visible-part-of-clip-path

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!