2

I'm using bootstrap 5. I want to use an img tag to display a different image for mobile/tablet/desktop. I'm trying with this code but I'm unable to set correctly the breakpoints for the wrapper divs using the display utilities of the bootstrap framework.

If is possible, I want to have three image tags instead of three different divs that take the 100% of the window height.

If you see the code, I have a sort of modal to display on top of the background image that needs to fit for each breakpoint all the screen space available. I've tried with img-fluid w-100 h-100 classes but the result isn't really nice and I can't crop the background. I'm using vue for the front-end, I'm not a front-end dev.

Thank you.

<template>
  <div class="container-fluid p-0">
    <div class="row m-0">
<!-- This div with the image needs to be displayed only on mobile sm breakpoint -->
      <div class="col-lg-12 d-md-none d-lg-none d-sm-block p-0">
        <img class="img-fluid w-100" src="@/assets/sm-background.png">   
      </div>
<!-- This div with the image needs to be displayed only on tablet md breakpoint -->
      <div class="col-lg-12 d-none d-sm-none d-lg-none d-md-block p-0">
        <img class="img-fluid w-100" src="@/assets/md-background.png">   
      </div>
<!-- This div with the image needs to be displayed only on desktop lg breakpoint -->
      <div class="col-lg-12 d-none d-sm-none d-md-none d-lg-block p-0">
        <img class="img-fluid w-100" src="@/assets/lg-background.png">   
      </div>

      <div class="col-sm-12 col-md-6 col-lg-6 mx-auto position-absolute" id="checkModal">
        <div class="card">
          <div class="card-body">
            <h4>Age verification required</h4>
            <p>...</p>
            
            <input type="date" class="form-control" v-model="birthDate" >
            
            <input type="passwrd" class="form-control" v-model="passwor" >

            <button class="btn btn-primary" @click.prevent="unlockContent()">Conferma</button>

          </div>
        </div>
      </div>

    </div>
  </div>
</template>

<script>

export default {
  name: 'App',
  data() {
    return {
      birthDate: '',
      password: ''
    }
  },
  mounted() {

  },
  methods: {
    unlockContent() {
      console.log(this.birthDate, this.password);
    }
  }
}
</script>

<style>
/* #app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
} */
#checkModal {
  top: 14%;
  left: 0;
  right: 0;
  z-index: 1;
}
</style>

´``
newbiedev
  • 2,607
  • 3
  • 17
  • 65

1 Answers1

9

Note: Section 1 answers the original question (d-* usage) but is not recommended for images as browsers may preload hidden images. However, d-* classes are still useful to display other elements by breakpoint.


1. d-* classes

Bootstrap classes are mobile first, so we don't need to define every breakpoint. Whatever we define at smaller breakpoints will cascade up to larger breakpoints until overridden.

So assuming OP's device definitions, we can use these display classes:

DEVICE SCREEN SIZE CLASSES
mobile visible below md d-md-none
tablet visible only on md d-none d-md-block d-lg-none
desktop hidden below lg d-none d-lg-block

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<!-- visible below md -->
<img class="d-md-none img-fluid w-100" alt="mobile alt text" src="https://via.placeholder.com/600x50/8da0cb/000000?text=600x50+for+breakpoint+%3C=+sm">
<!-- visible only on md -->
<img class="d-none d-md-block d-lg-none img-fluid w-100" alt="tablet alt text" src="https://via.placeholder.com/900x75/fc8d62/000000?text=900x75+for+breakpoint+==+md">
<!-- hidden below lg -->
<img class="d-none d-lg-block img-fluid w-100" alt="desktop alt text" src="https://via.placeholder.com/1200x100/66c2a5/000000?text=1200x100+for+breakpoint+%3E=+lg">

Expanded cheatsheet for hiding elements:

SCREEN SIZE            CLASSES
---------------------------------------------------
hidden on all          d-none
hidden only on xs      d-none d-sm-block
hidden only on sm      d-sm-none d-md-block
hidden only on md      d-md-none d-lg-block
hidden only on lg      d-lg-none d-xl-block
hidden only on xl      d-xl-none d-xxl-block
hidden only on xxl     d-xxl-none
hidden below sm        d-none d-sm-block
hidden below md        d-none d-md-block
hidden below lg        d-none d-lg-block
hidden below xl        d-none d-xl-block
hidden below xxl       d-none d-xxl-block
---------------------------------------------------
visible on all         d-block
visible only on xs     d-block d-sm-none
visible only on sm     d-none d-sm-block d-md-none
visible only on md     d-none d-md-block d-lg-none
visible only on lg     d-none d-lg-block d-xl-none
visible only on xl     d-none d-xl-block d-xxl-none
visible only on xxl    d-none d-xxl-block
visible below sm       d-sm-none
visible below md       d-md-none
visible below lg       d-lg-none
visible below xl       d-xl-none
visible below xxl      d-xxl-none

2. <picture> element (recommended for images)

Browser behavior for preloading hidden images has been inconsistent over time and across browsers. Since loading hidden images hurts page load times, it's recommended to avoid the d-none approach for images.

Best practice for breakpointed images (aka "art direction"):

  1. Use <picture> with multiple <source> tags conditioned on media strings.

  2. Since css classes don't work in media strings, use bootstrap's breakpoint pixels:

    BREAKPOINT DIMENSIONS
    sm ≥576px
    md ≥768px
    lg ≥992px
    xl ≥1200px
    xxl ≥1400px

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<picture>
  <!-- show this up to sm -->
  <source media="(max-width: 596px)" srcset="https://via.placeholder.com/600x50/8da0cb/000000?text=600x50+for+breakpoint+%3C=+sm">
  <!-- else show this up to md -->
  <source media="(max-width: 768px)" srcset="https://via.placeholder.com/900x75/fc8d62/000000?text=900x75+for+breakpoint+==+md">
  <!-- else show this -->
  <img class="img-fluid w-100" alt="alt text for all sources" src="https://via.placeholder.com/1200x100/66c2a5/000000?text=1200x100+for+breakpoint+%3E=+lg">
</picture>
tdy
  • 36,675
  • 19
  • 86
  • 83
  • 1
    The recommended way to display responsive images is discussed in this MDN article: [Responsive images](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#art_direction) *(specifically read the "Art Direction" topic)*. –  Apr 07 '21 at 08:00
  • 1
    @Vino I simply have three images of different sizes that will fit the breakpoint. I'm not deisgner so I was looking for a quick css trick to get the things in order ;) – newbiedev Apr 07 '21 at 08:15