# Images

  • When you set the width and height of an image in CSS, it overwrites the settings of the HTML width and height attributes
  • In the example below:
    • The first image has only width and height attributes on the img tag (400px * 300px)
    • The second image (#img2) has the same width and height attributes on the img tag (400px * 300px), but in CSS the width and height is set to 200px * 150px
  • CONCLUSION: As soon as you write the image dimensions in CSS, you may omit the width and height attributes in HTML!
    
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quas quae, distinctio enim quasi expedita dolor, amet sunt unde. Quaerat fugiat ipsum deserunt sequi, praesentium suscipit? Id itaque delectus, quia eaque!</p>
<p>
    <img width="400" height="300" src="https://picsum.photos/id/104/400/300" alt="waves">
</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quas quae, distinctio enim quasi expedita dolor, amet sunt unde. Quaerat fugiat ipsum deserunt sequi, praesentium suscipit? Id itaque delectus, quia eaque!</p>
<p>
    <img id="img2" width="400" height="300" src="https://picsum.photos/id/104/400/300" alt="waves">
</p>

    
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; font-size: 1rem; line-height: 1.5; padding: 1rem; }
p { margin-bottom: 1rem; }
#img2 { width: 200px; height: 150px; }
    

# Responsive images

  • Images sometimes have very annoying side effects, even with a proper viewport meta tag
    • Left: the width of the image is smaller than the viewport
    • Middle: the width of the image is larger than the viewport, so a horizontal scroll bar appears (when you touch the screen)
    • Right: the image is made responsive, which means that the image is scaled such that its width fits inside the screen's viewport

Responsive or not

  • For a responsive image, you set
    • the max-width (or width) to 100%
      • Use max-width if the image width can't be larger than its original width
      • Use width if the image width may be larger than its original width (the image is enlarged/upscaled)
    • the height to auto

 
 


img {
    max-width: 100%;     /* use `width` instead of `max-width` if the image is also allowed to scale up */
    height: auto;
}
1
2
3
4
  • Open this pen in a new browser window to see the difference between the two images
    
<h1>Responsive images</h1>
<figure>
    <img src="https://picsum.photos/id/1043/400/300" alt="forest">
    <figcaption>Responsive image with <span>max-width: 100%</span></figcaption>
</figure>
<figure>
    <img class="max" src="https://picsum.photos/id/1043/400/300" alt="forest">
    <figcaption>Responsive image with <span>width: 100%</span></figcaption>
</figure>

    
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; }
h1, figure { margin-bottom: 1rem; }
img { max-width: 100%; height: auto; }
.max { width: 100%; }
figcaption span { font-family: monospace; font-weight: bold; color: white; background-color: steelblue; padding: .3rem; }
    

REMARK

Be careful with width: 100% as upscaling images always comes with quality loss

# Crop/resize images

  • First, take a quick look at the example: images with different breakpoint
    • On a small and large screen, all images are in landscape mode and are responsive
    • On a medium screen, all images are in portret mode and have a fixed width and height
  • There are two ways to accomplish this:
    • The hard way with Photoshop and JavaScript 😏
      • Open Photoshop and make two versions for every image (a landscape version and a portret version)
      • Add some JavaScript to switch between the different image versions at different breakpoints
    • The easy way with pure CSS 😃
      • Use the CSS property object-fit to crop and/or resize the original image on different breakpoints
      • Use the CSS property object-position to position the cropped image
  • Let's start with a simple example to explain these two properties
    
<h1>Image crop/resize with object-fit</h1>
<figure>
    <img src="https://picsum.photos/id/1005/270/180" alt="person">
    <img src="https://picsum.photos/id/1011/600/200" alt="kayak">
    <img src="https://picsum.photos/id/1074/300/500" alt="lion">
    <figcaption>Default: <span>object-fit: fill;</span></figcaption>
</figure>
<figure class="contain">
    <img src="https://picsum.photos/id/1005/270/180" alt="person">
    <img src="https://picsum.photos/id/1011/600/200" alt="kayak">
    <img src="https://picsum.photos/id/1074/300/500" alt="kayak">
    <figcaption><span>object-fit: contain;</span></figcaption>
</figure>
<figure class="none">
    <img src="https://picsum.photos/id/1005/270/180" alt="person">
    <img src="https://picsum.photos/id/1011/600/200" alt="kayak">
    <img src="https://picsum.photos/id/1074/300/500" alt="kayak">
    <figcaption><span>object-fit: none;</span></figcaption>
</figure>
<figure class="cover">
    <img src="https://picsum.photos/id/1005/270/180" alt="person">
    <img src="https://picsum.photos/id/1011/600/200" alt="kayak">
    <img src="https://picsum.photos/id/1074/300/500" alt="kayak">
    <figcaption><span>object-fit: cover;</span></figcaption>
</figure>
<figure class="position">
    <img src="https://picsum.photos/id/1005/270/180" alt="person">
    <img src="https://picsum.photos/id/1011/600/200" alt="kayak">
    <img src="https://picsum.photos/id/1074/300/500" alt="kayak">
    <figcaption><span>object-fit: none; object-position: top left;</span></figcaption>
</figure>

    
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
body { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; }
h1 { margin-bottom: 1rem; }
figure { margin-bottom: 2rem; }
figcaption span { font-family: monospace; font-weight: bold; color: white; background-color: steelblue; padding: .3rem; }
img { border: 1px solid #000; background-color: #f5a1a1; margin: 0 1rem 1rem 0; width: 300px; height: 200px; }
.contain img { object-fit: contain; }
.none img { object-fit: none; }
.cover img { object-fit: cover; }
.position img { object-fit: none; object-position: top left; }
    
  • Let's start with three images with different dimensions
    • Left image: 270px * 180px
    • Middle image: 600px * 200px
    • Right image: 300px * 500px

Images without CSS

# object-fit: fill (default)

  • Give all images a fixed width and height

 
 


img {
    width: 300px;
    height: 200px;
}
1
2
3
4
  • Only the first image looks fine because it has the same aspect ratio as the CSS properties
  • The two other images are scaled but squeezed/stretched to fit into the image box
  • If you don't specify the object-fit property, the browser uses object-fit: fill; as the default setting

Object-fit fill

# object-fit: contain

  • All images are scaled to fit into the image box but maintain their original aspect ratio



 


img {
    width: 300px;
    height: 200px;
    object-fit: contain;
}
1
2
3
4
5

Object-fit contain

# object-fit: none

  • Only images that are larger than the box dimensions are scaled down to fit into the image box
  • All images maintain their aspect ratio, but some parts are clipped



 


img {
    width: 300px;
    height: 200px;
    object-fit: none;
}
1
2
3
4
5

Object-fit contain

# object-fit: cover (most used)

  • All images are scaled up or down to fit into the image box
  • All images maintain their aspect ratio, but some parts are clipped

Object-fit cover

# object-position

  • As you can see in the above examples, images are centered (both horizontally and vertically) by default
  • You can change the position with the object-position property, e.g:




 


img {
    width: 300px;
    height: 200px;
    object-fit: none;
    object-position: top left;
}
1
2
3
4
5
6
  • The values for object-position (see also interactive example) are the same as for background-position:
    • first value for vertical positioning: top, center, bottom or use fixed units like px, %, ...
    • second value for horizontal positioning: left, center, right or use fixed units like px, %, ...
    • horizontal and vertical positioning values are interchangeable:
      object-position: top left; = object-position: left top;

Object-position

# Example

    
<div class="container">
    <h1>Images with different breakpoints</h1>
    <figure>
        <img src="https://picsum.photos/id/1015/300/200" alt="nature1">
        <img src="https://picsum.photos/id/1016/300/200" alt="nature2">
        <img src="https://picsum.photos/id/1019/300/200" alt="nature3">
        <img src="https://picsum.photos/id/1022/300/200" alt="nature4">
    </figure>
</div>

    
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
body { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; background-color: lightblue; }
.container { padding: 1rem; margin: 2rem auto; border: 1px solid #000; background-color: whitesmoke; }
h1 { font-size: 1.5rem; margin-bottom: 1rem; text-align: center; }
figure { text-align: center; }
img { width: 100%; height: auto; }
@media screen and (min-width: 600px) { body { background-color: #D5D971; }
img { width: 125px; height: 200px; object-fit: cover; } }
@media screen and (min-width: 800px) { body { background-color: #f1c6b1; }
img { width: 45%; height: auto; } }
    

# Small screen (below 600px)

  • All images are responsive

 
 


img {
    width: 100%;
    height: auto;
}
1
2
3
4

# Medium screen (between 600px and 800px)

  • All images
    • have a fixed width and height
    • are cropped symmetrically (around the center/middle)



 


img {
    width: 125px;
    height: 200px;
    object-fit: cover;
}
1
2
3
4
5

# Larger screen (above 800px)

  • All images are responsive again

 
 


img {
    width: 45%;
    height: auto;
}
1
2
3
4

# Oversized background image on body

TIP

  • Just as for images, you can also control the size/fit and positioning of background images

    • For size/fit:
    element sizing possible values
    image object-fit contain, cover, fill and none
    background image background-size only contain and cover (and values in px or %)
    • For positioning:
    element positioning possible values
    image object-position top, center, bottom, left, right, px, %, ...
    background image background-position top, center, bottom, left, right, px, %, ...
  • The following example/exercise demonstrates how to set a fixed, oversized background image on the body (or on the html element)
  • Let's start with a background-color and a background-image of 800px * 600px on the body
    • As you now know from a previous chapter, the background will copy itself horizontally and vertically
  • Open the pen below in full screen mode to see the effect
    
<h1>Full page background</h1>
<div>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat labore rerum ea rem sed nesciunt veniam incidunt vitae quidem facilis odio, similique enim autem dicta, libero illo amet tempora soluta.</p>
</div>

    
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; background-color: #bcbb9d; background-image: url(https://picsum.photos/id/100/800/600); /* background-size: cover; */ /* background-attachment: fixed; */ /* background-position: top center; */ }
h1 { margin-bottom: 1rem; }
div { background-color: rgba(255, 255, 255, .2); padding: 1rem; height: 110vh; border: 1px solid #000; }
    

# Exercise

  • Follow these three steps to transform the background into a static, fullscreen background image
    1. Cover the background with the whole image: background-size: cover;
      • Depending on the size of the browser window, you only see a small portion of the original image
      • By default, you see the top left corner of the image
    2. Fix the background image (so it doesn't scroll with the content of the page) with background-attachment: fixed;
    3. Position the background image, e.g. background-position: top center;

REMARKS

  • To limit the loading time of web pages, it is best practice not to use too large background images: background images must remain below 200kB
  • Always make sure that the background-color matches the colour tones in the background-image, so that a suiting colour is shown when loading the page
  • If you study the CSS code in detail, you notice that the div on the page gets a height of 110vh or 110% of the viewport height. As such, the div is taller than the screen and a scrollbar will be shown. Read more on viewport units (viewport height vh, viewport width vw, ...) in CSS Viewport Units: A Quick Start.
EMMET instruction result
bga + TAB background-attachment: ;
bga:f + TAB background-attachment: fixed;
bgp + TAB background-position: 0 0;

# Filters

  • One of the nice recent features in CSS3 is the addition of filters on images which reduces the need to use photo editing programs

https://caniuse.com/#feat=css-filters

  • Some examples:
function values
blur() px
brightness() from 0% to 100% (or from 0 to1)
contrast() %
grayscale() from 0% to 100% (or from 0 to1)
invert() from 0% to 100% (or from 0 to1)
opacity() from 0% to 100% (or from 0 to1)
saturate() from 0% to 100% (or from 0 to1)
sepia() from 0% to 100% (or from 0 to1)
hue-rotate() ..deg
drop-shadow() hoff voff blur color
    
<h1>Filters</h1>
<figure>
    <img class="blur" src="https://picsum.photos/id/28/250/250" alt="">
    <figcaption><span>blur(3px)</span></figcaption>
</figure>
<figure>
    <img class="brightness" src="https://picsum.photos/id/281/250/250" alt="">
    <figcaption><span>brightness(.7)</span></figcaption>
</figure>
<figure>
    <img class="contrast" src="https://picsum.photos/id/289/250/250" alt="">
    <figcaption><span>contrast(200%)</span></figcaption>
</figure>
<figure>
    <img class="grayscale" src="https://picsum.photos/id/287/250/250" alt="">
    <figcaption><span>grayscale(80%)</span></figcaption>
</figure>
<figure>
    <img class="invert" src="https://picsum.photos/id/292/250/250" alt="">
    <figcaption><span>invert(.8)</span></figcaption>
</figure>
<figure>
    <img class="opacity" src="https://picsum.photos/id/299/250/250" alt="">
    <figcaption><span>opacity(25%)</span></figcaption>
</figure>
<figure>
    <img class="saturate" src="https://picsum.photos/id/292/250/250" alt="">
    <figcaption><span>saturate(30%)</span></figcaption>
</figure>
<figure>
    <img class="sepia" src="https://picsum.photos/id/292/250/250" alt="">
    <figcaption><span>sepia(100%)</span></figcaption>
</figure>
<figure>
    <img class="hue-rotate" src="https://picsum.photos/id/306/250/250" alt="">
    <figcaption><span>hue-rotate(90deg)</span></figcaption>
</figure>
<figure>
    <img class="drop-shadow" src="https://picsum.photos/id/30/430/250" alt="">
    <figcaption><span>drop-shadow(.5rem .5rem 5px rgba(0, 0, 0, .7))</span></figcaption>
</figure>

    
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; }
h1 { margin-bottom: 1rem; }
figure { display: inline-block; text-align: center; margin-bottom: 2rem; }
.blur { filter: blur(3px); }
.brightness { filter: brightness(.7); }
.contrast { filter: contrast(200%); }
.grayscale { filter: grayscale(80%); }
.invert { filter: invert(.8); }
.opacity { filter: opacity(25%); }
.saturate { filter: saturate(30%); }
.sepia { filter: sepia(100%); }
.hue-rotate { filter: hue-rotate(90deg); }
.drop-shadow { filter: drop-shadow(.5rem .5rem 5px rgba(0, 0, 0, .7)); }
figcaption span { font-family: monospace; font-weight: bold; color: white; background-color: steelblue; padding: .3rem; }
    

# Clipping path

  • Another new, but not yet widely supported feature is clip-path

https://caniuse.com/#feat=css-clip-path

  • A good site to help you in creating such a clip-path is https://bennettfeely.com/clippy/
    • A number of sample images are used in combination with predefined shapes that you can adjust
    • Keep a close eye on the dimensions of the image you want to clip
    • The code you need to copy into CSS can be found at the bottom left Clippy
    

Clipping path

<figure> <img src="https://picsum.photos/id/402/60/280" alt=""> <img class="t" src="https://picsum.photos/id/34/198/280" alt=""><img class="f" src="https://picsum.photos/id/397/132/280" alt=""> </figure>
    
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; }
h1 { margin-bottom: 1rem; }
img { margin-right: 1rem; }
.t { clip-path: polygon(0 0, 100% 0, 100% 20%, 65% 20%, 65% 100%, 35% 100%, 35% 20%, 0% 20%); }
.f { clip-path: polygon(0 0, 100% 0, 100% 20%, 45% 20%, 45% 35%, 100% 35%, 100% 55%, 45% 55%, 45% 100%, 0% 100%); }
    

REMARK

For Safari users, the clip-path statement has to be preceded by a similar line with the vendor prefix -webkit, as this property is not yet fully supported by Safari. For example:


 



.t {
    -webkit-clip-path: polygon(0 0, 100% 0, 100% 20%, 65% 20%, 65% 100%, 35% 100%, 35% 20%, 0% 20%);
    clip-path: polygon(0 0, 100% 0, 100% 20%, 65% 20, 65% 100%, 35% 100%, 35% 20%, 0% 20%);
}
1
2
3
4
Last Updated: 10/10/2021, 12:05:33 PM