Recent projects have involved dealing with image-related layouts, and I have to say that images are a bit of a struggle to get the perfect presentation. Because pictures vary in size or scale. So if you want images of different sizes to look good, you need to find the right way.

And pictures are often indispensable. After all, a picture is worth a thousand words, and sometimes pictures can be very good.

For example, emoticons that we use every day can often express information that we cannot describe with words. For example, cartoons that we often see on official wechat account can make us enjoy reading even though they are only a few words.

Of course, if we do picture website, that picture processing is not around the topic. Because of the image processing experience is not much, so learn while using. Today, I will sort out the knowledge related to pictures recently.

For example, how can a single image be better displayed? What are the implementation methods of waterfall flow layout that you don’t know?

Let’s get straight to the point. Let’s start with the presentation of individual images.

Set the width or height to 100%

Because of the uniqueness of the image itself:

  1. If the width and height are not set, it will be displayed in the web page according to the original size. How big is it? How big is it.
  2. It will be stretched out of shape in the case of non-proportional scaling.
  3. When you set the width or height, it keeps the original aspect ratio and scales.

<style lang="scss" scoped>
.box1 {
  width: 150px;
  height: 150px;
  border: 2px solid red;
}
.box2 {
  width: 150px;
  height: 100px;
  border: 2px solid red;
  img {
    display: block;
    width: 100%;
    height: 100%;
  }
}
</style>
Copy the code

Obviously, when we adopt 1 or 2 methods, it is very destructive and cannot be applied to real projects.

This is why we often use the third option in projects, which is to set the height or width. It’s going to keep scaling.

<style lang="scss" scoped>
.box {
  width: 150px;
  height: 150px;
  border: 2px solid red;
}
.img1 {
  width: 100%;
}
.img2 {
  height: 100%;
}
</style>
Copy the code

The problem is that the image is either out of the container or blank until the container’s aspect ratio equals the image’s aspect ratio.

For images that are out of the container, we can use overflow: Hidden to hide the out part. The pictures are well displayed. But we also lose some of the visual area of the image.

So it’s up to you to decide whether to hide part of the image or leave it blank. Some friends will say, our product said, the picture deformation is ok, you just fill the container for me. Ok…

Even so, you should read this article carefully, because the need is ever-changing, you may need it someday.

Another friend said, “What should we do if these two kinds of products do not meet our product needs? Is there any other way?” The answer is absolutely necessary. Let’s see.

object-fit

CSS3’s object-fit property is used to specify how the contents of the “replaceable elements” fit into the container. It has five different values. Respectively, the fill | contain | cover | none | scale – down. Let’s look at the effects and explain what they mean.

<template>
  <div class="box">
    <img src="https://picsum.photos/id/1027/200/300"/>
  </div>
</template>
<style lang="scss" scoped>
.box {
  width: 150px;
  height: 150px;
  border: 2px solid red;
  img {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }
}
</style>

Copy the code

Seeing the above display, it’s not that hard to understand.

  • Fill: will fill the entire container, regardless of the aspect ratio, so it will be stretched and deformed.
  • Contain: will scale into the container, maintain the width to height ratio.
  • Cover: will maintain the scale, content must be greater than or equal to the container size, then cropped.
  • None: Keep the original size of the image.

Scale-down has two manifestations so let’s look at it separately.

  • Scale-down: selects one of none or contain. The principle is that if it is small, it will behave like a contain. When the image is small, it behaves like None. That is, who chooses who is smaller.

width: 100%; width: 100%; height: 100%; It fills the entire container.

But why does the content display have a different effect left me wondering. In the spirit of discovery, I went to find the answer.

The tag creates a placeholder for the referenced image, as described by W3c.

Zhang Xinxu also pointed out in his semi-in-depth understanding of CSS3 Object-position /object-fit attributes:

The element is actually separate from the content. is like a shell around the content. All you control is the size of the element. The size of the content is controlled by the Object-fit property.

In summary, is a spatial placeholder and does not control the content. I see. I feel like I’m making progress again. It’s a wonderful feeling to discover something new every time you explore. Especially also put it sorted out the article, provide everyone to learn, feel cattle force coax coax with lightning.

With this in mind we can manipulate images more easily. Is that the end of all this? No, no, no, no. This is just the beginning. This is where it gets better. The layout at the back is even more exciting.

Multi-image layout

All that has been said above is single image display. As long as we put the picture into the container in the right way. What if it’s a list of pictures? Or a website dedicated to images may have a large number of images in all kinds of sizes and proportions.

Suppose that to achieve an image gallery effect, we first give the image a float: left, but because the size of the image is different, each image has a different height, and the image in the next row will get stuck, causing the layout to be distorted.

At this point you have to set the height of the container so that the image is aligned at the bottom, but as we mentioned at the beginning of this article, the image is either out of the height of the container or left blank.

If you use object-fit attributes to control content according to business requirements, it seems to accomplish the task.

Set the value to contain, the layout is ok, but it is really ugly. If YOU set cover, if the image is too big a lot of the content will be lost. How to do? What’s the solution? This is where the waterfall flow layout comes in handy.

Waterfall flow layout will not be distorted and will maximize the content of the image. So this is the layout that many image sites choose.

Waterfall flow layout has two forms: one is equal width type, the other is equal height type. Let’s talk about equal width first.

Equal width waterfall flow

What is the idea of your implementation that you see above? Think about it for a few seconds, and see if any of these implementations think the same way you do.

1. JS calculates the number of columns

Key ideas:

  • First set the column width, then calculate the number of columns that can be displayed.
  • Add images to each column.

Key code:

<script> export default { methods: {/ / computing getColNumbers image sequence () {let clientWidth = this. $refs. Waterfall. ClientWidth enclosing colNumbers = math.h floor (clientWidth GetColNumbers () {this.getcolNumbers () for (let I = 0; i < 17; i++) { let colIndex = i % this.colNumbers let url = require(`@/assets/images/${i}.jpg`) if (this.imgList[colIndex]) { this.imgList[colIndex].push(url) } else { this.$set(this.imgList, colIndex, [url]) } } }, } } </script>Copy the code

Advantages: clear and simple thinking, do not need to do too much calculation, just calculate the number of columns to display and then add pictures.

Disadvantages: The end of each column may not be friendly, some columns may be long, some may be short.

Idea 2. Use absolute positioning

Key ideas:

  • First set the column width, then calculate the number of columns that can be displayed.
  • Set the image to absolute position, then calculate the top and left values for each image.
  • Top = 0, left = index * column width.
  • Starting with the second line, place each image under the shortest column. Then increase the column height, which changes, and the next image looks for the other shortest columns. And you keep doing that.

Key code:

<script> export default { methods: {/ / computing getColNumbers image sequence () {let clientWidth = this. $refs. Waterfall. ClientWidth enclosing colNumbers = math.h floor (clientWidth GetColNumbers () {this.getcolNumbers () for (let I = 0; i < 17; i++) { let image = new Image() let url = require(`@/assets/images/${i}.jpg`) image.src = url image.onload = () => { this.render({ index: i, url: url, ratio: image.width / image.height }) } } }, ImgInfo {let colIndex = imginfo.index % this.colNumbers imginfo.left = colIndex * this.colWidth // top = 0, Imginfo.index < this.colnumbers) {imginfo.top = 0 this.colheight [colIndex] = this.colWidth/imginfo.ratio } else {let minHeight = math.min. apply(null, This.colheight) let minIndex = this.colheight. IndexOf (minHeight) // Imginfo.left = minIndex * this.colWidth // Add the height to this.colHeight[minIndex] += this.colWidth / imgInfo.ratio } this.imgList.push(imgInfo) } } } </script>Copy the code

Advantage: Since each append image is the shortest column, the display at the end is much friendlier than in Idea 1.

Disadvantages: No rendering will calculate a top, left value. And the pictures are out of order.

3. The CSS3 column attribute

Key ideas:

  • Column-count: specifies the number of columns
  • Column-gap: Sets the space between columns

Key code:

<template>
  <div class="waterfall-width-column">
    <div class="image-box" v-for="img in imgList" :key="img">
      <img :src="img" alt="" />
    </div>
  </div>
</template>
<style lang="scss" scoped>
.waterfall-width-column {
  column-count: 3;
  column-gap: 10px;
  .image-box {
    img {
      display: block;
      width: 100%;
    }
  }
}
</style>
Copy the code

Advantages: Much simpler, no extra computation, efficient CSS rendering directly.

Disadvantages: Images are ordered from top to bottom, depending on business requirements. And the number of columns is fixed.

However, you can try to set different column numbers through media queries

@media (min-width: 768px) { .waterfall-width-column { column-count: 3; } } @media (min-width: 992px) { .waterfall-width-column { column-count: 4; } } @media (min-width: 1200px) { .waterfall-width-column { column-count: 6; }}Copy the code

Equal height waterfall flow

So with that out of the way, let’s talk about contour.

JS computes scaling

  • First, a reference height is given
  • The image gets the width below the base height, and then calculates how many images can fit in each row
  • Each line must be smaller than the container width, and then the line is scaled to the container size. After recalculating the magnified height.

Key code:

<script> export default {data() {return {baseHeight: 200, // imgList: [[]], // Save each row with 2d data rowWidth: }}, methods: {loadImage() {for (let I = 0; i < 17; i++) { let image = new Image() let url = require(`@/assets/images/${i}.jpg`) image.src = url image.onload = () => { this.compare({ url: url, width: this.baseHeight * (image.width / image.height), height: this.baseHeight }) } } }, Total / / resized image width compared to screen width compare (image) {/ / container width let clientWidth = this. $refs. Waterfall. ClientWidth this. / / calculation per line width rowWidth + = Image.width // If the width is larger than the container width, remove the extra width, If (this.rowWidth > clientWidth) {// Subtract each CSS padding margin clientWidth = clientWidth - This.imglist [this.rowcount].length * 10 this.rowWidth = this.rowwidth - image.width // Set the height to let growAfterHeight = (clientWidth * this.baseHeight) / this.rowWidth this.imgList[this.rowCount].forEach(item => { item.height = This.rowwidth = image.width this.rowcount ++ this.imglist $set(this.imglist, this.rowcount, this.rowcount) [image]) } else { this.imgList[this.rowCount].push(image) } } } } </script>Copy the code

Advantage: The content of the image is fully displayed and not hidden.

Disadvantages: Repeated calculations and scaling.

Idea 2. Flex layout

  • First give the image a fixed height, then take advantage of flex-Grow’s scaling feature
  • Give the image an Object-fit property so that it fills the container in proportion
<template>
  <div class="waterfall-height-css">
    <div class="image-box" v-for="img in imgList" :key="img.url">
      <img :src="img.url" />
    </div>
  </div>
</template>
<script>
<style lang="scss" scoped>
.waterfall-height-css {
  display: flex;
  flex-wrap: wrap;
  .image-box {
    flex-grow: 1;
  }
  img {
    display: block;
    min-width: 100%;
    height: 200px;
    object-fit: cover;
  }
}
</style>
Copy the code

At this point, you will see that each line of the image is nicely displayed. But there is only one small problem with the last line.

Imagine if the last row had only one image, it would be scaled to fill the row, resulting in a very small portion of the image.

So, we can leave the last line of the image unscaled. Just add the following CSS properties.

<style lang="scss" scoped>
.waterfall-height-css {
  &:after {
    content: '';
    display: block;
    flex-grow: 99999;
  }
}
</style>
Copy the code

Because the flex-grow: 99999 value is very large, it takes up almost all of the remaining space in the last row. As a result, the image will be displayed at full size instead of being scaled to cover the entire row.

Advantages: Simple CSS setup and efficient rendering.

Disadvantages: loss of visible area of the image.

Here, we introduce the display characteristics of pictures and how to use object-fit for content control.

For multi-image layouts, waterfall layout is a very good choice for a more reasonable display of images. Of course, if the business needs to display friendly and beautiful images do not require, you can use object-Fit control content.

But I think the waterfall layout is also one of the content we should master, even if it is not needed at this time, you can also save the article for a rainy day, the article uses a variety of ways to implement, you can choose the most suitable for your needs.

Of course, there are a lot of details left unaddressed in the case, such as how to optimize the experience when the browser window changes and the image reloads will flash. Friends might as well try to optimize their own. Hands-on practice is an important means of mastering skills.

Code address for all cases in this article: gitHub address

2T free technical resources, including but not limited to: front-end, Python, Java, Android, products, etc. Public number back to “1024”, you can get free!

Public number: six small dengdeng, more dry goods article, background reply “add group” take you into the quality of communication group.