1

I am trying to make it so that as an image loads in my bootstrap card, it either has a placeholder image (to keep the card the same size) or a loading spinner. I cannot figure out how to do this, here is my current card html:

<div class="card mb-4" data-clickable="true" data-href="#">
    <img class="card-img-top" src="https://via.placeholder.com/700x400" alt="Card image cap">

    <div class="card-body">
          <h5 class="card-title">John Doe</h5>
    </div>

    <div class="card-footer">
        <small class="text-muted">Last updated 3 mins ago</small>
    </div>
</div>

Obviously the placeholder will be replaced with the full image, but my current problem is that before the image loads on slow connection, the card collapses since the image isn't there to fill it.

johannchopin
  • 13,720
  • 10
  • 55
  • 101
S.Stevens
  • 378
  • 1
  • 5
  • 18
  • You can refer this link: https://stackoverflow.com/a/41730965/6029001 – Rohan Rao Oct 26 '19 at 14:08
  • I actually managed to sort of get something to work, but am now facing a weirder issue, the code says "imgPreload is not a function" if I use both jquery/2.2.4/jquery.min.js (the one required for the loading to work) and then also jquery-3.2.1.slim.min.js as required for the rest of bootstrap. If I remove the latter it works. I am very confused... – S.Stevens Oct 26 '19 at 22:49
  • Ok I checked out the link you sent- I can't figure out how I'd apply this specifically to the images for the card header in the code above? I tried to follow the comment someone left but I don't know what to put in place of #imageID? and surely I'd have to put a long list of every image id used. Also, is there a way to use this with the built in spinners in bootstrap? It would cut out a lot of CSS. Sorry for the questions I'm new to all this. – S.Stevens Oct 26 '19 at 23:05
  • I also tried that link and couldn't seem to get it to work. – S.Stevens Oct 27 '19 at 16:23

1 Answers1

0

Okay, so here is what you want I guess. Run the output first and check how it works. I hope you wanted this as per your request.

I have included JS file, then CSS followed by HTML. It will first show the Loading... text, and then will show your image on the card.

$(window).on('load', function(){
  setTimeout(showImage, 2000); 
});
function showImage(){
    $( ".card-lbl-top" ).fadeOut(500, function() {
     $(".card-img").append('<img class="card-img" id="img-card" src="https://via.placeholder.com/700x400" alt="Card image cap">');
  });  
}
  .loader,
        .loader:after {
            border-radius: 50%;
            width: 10em;
            height: 10em;
        }
        .loader {            
            margin: 60px auto;
            font-size: 10px;
            position: relative;
            text-indent: -9999em;
            border-top: 1.1em solid rgba(255, 255, 255, 0.2);
            border-right: 1.1em solid rgba(255, 255, 255, 0.2);
            border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
            border-left: 1.1em solid #ffffff;
            -webkit-transform: translateZ(0);
            -ms-transform: translateZ(0);
            transform: translateZ(0);
            -webkit-animation: load8 1.1s infinite linear;
            animation: load8 1.1s infinite linear;
        }
        @-webkit-keyframes load8 {
            0% {
                -webkit-transform: rotate(0deg);
                transform: rotate(0deg);
            }
            100% {
                -webkit-transform: rotate(360deg);
                transform: rotate(360deg);
            }
        }
        @keyframes load8 {
            0% {
                -webkit-transform: rotate(0deg);
                transform: rotate(0deg);
            }
            100% {
                -webkit-transform: rotate(360deg);
                transform: rotate(360deg);
            }
        }
        #loadingDiv {
            position:absolute;;
            top:0;
            left:0;
            width:100%;
            height:100%;
            background-color:#000;
        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card mb-4" data-clickable="true" data-href="#">
    <div class="card-img"></div>
    <div class="card-lbl-top">Loading..</div>

    <div class="card-body">
          <h5 class="card-title">John Doe</h5>
    </div>

    <div class="card-footer">
        <small class="text-muted">Last updated 3 mins ago</small>
    </div>
</div>

EDIT:

For the loader, please donwload any image of your choice from the link: https://www.google.com/search?rlz=1C1CHBF_enIN870IN870&biw=1366&bih=657&tbm=isch&sxsrf=ACYBGNQOR87uoUNkaowBsmaX4woBJbxr5Q%3A1572240743786&sa=1&ei=Z322Xf_RL5u9rQHh77KgAQ&q=loading+gif&oq=loading+gif&gs_l=img.3..35i39j0i67j0j0i67j0l6.1962.1962..2270...0.0..0.139.139.0j1......0....1..gws-wiz-img.YRsD96fve2c&ved=0ahUKEwi_oaOYnb7lAhWbXisKHeG3DBQQ4dUDCAc&uact=5#imgrc=Oi3RjeMxzZDEAM:

When you download it to your local machine, you need to do a small change in your HTML markup to replace the Loading... text with your downloaded Loader image. And here is the change:

$(window).on('load', function(){
  setTimeout(showImage, 2000); 
});
function showImage(){
    $( ".card-lbl-top" ).fadeOut(500, function() {
     $(".card-img").append('<img class="card-img" id="img-card" src="https://via.placeholder.com/700x400" alt="Card image cap">');
  });  
}
.loader,
        .loader:after {
            border-radius: 50%;
            width: 10em;
            height: 10em;
        }
        .loader {            
            margin: 60px auto;
            font-size: 10px;
            position: relative;
            text-indent: -9999em;
            border-top: 1.1em solid rgba(255, 255, 255, 0.2);
            border-right: 1.1em solid rgba(255, 255, 255, 0.2);
            border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
            border-left: 1.1em solid #ffffff;
            -webkit-transform: translateZ(0);
            -ms-transform: translateZ(0);
            transform: translateZ(0);
            -webkit-animation: load8 1.1s infinite linear;
            animation: load8 1.1s infinite linear;
        }
        @-webkit-keyframes load8 {
            0% {
                -webkit-transform: rotate(0deg);
                transform: rotate(0deg);
            }
            100% {
                -webkit-transform: rotate(360deg);
                transform: rotate(360deg);
            }
        }
        @keyframes load8 {
            0% {
                -webkit-transform: rotate(0deg);
                transform: rotate(0deg);
            }
            100% {
                -webkit-transform: rotate(360deg);
                transform: rotate(360deg);
            }
        }
        #loadingDiv {
            position:absolute;;
            top:0;
            left:0;
            width:100%;
            height:100%;
            background-color:#000;
        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card mb-4" data-clickable="true" data-href="#">
    <div class="card-img"></div>
    <div class="card-lbl-top"><img src="https://miro.medium.com/max/1158/1*9EBHIOzhE1XfMYoKz1JcsQ.gif"/></div>

    <div class="card-body">
          <h5 class="card-title">John Doe</h5>
    </div>

    <div class="card-footer">
        <small class="text-muted">Last updated 3 mins ago</small>
    </div>
</div>
Rohan Rao
  • 2,505
  • 3
  • 19
  • 39
  • Thank you so much! It's nearly exactly what I wanted. A couple of small bits- how would I make it so that the loading part takes up the same size (ie has padding) so that the size doesn't jump? And, how would I replace the loading font with the built in bootstrap spinner classes? Thanks again :) – S.Stevens Oct 27 '19 at 18:36
  • Hmm I have tried to figure this out for myself and forgot to make it clear- each card is to have a different image, so this method would surely not work since the image is called in the Java Script? I feel as if I am over complicating something so basic- how else does everyone use images in a bootstrap card? I can't find any mention of how to do what I'm trying to do online elsewhere. – S.Stevens Oct 27 '19 at 23:23
  • @S.Stevens, don't worry about different images. If you give a same class name to all the images, JavaScript will find the class in a web page and apply the script to it. So, suppose you have 4 cards with similar functionality, you just need to mention the same class i.e. ".card-lbl-top" for each cards. JavaScript will find the class in a page and apply the script to it automatically. The only difference is you will need to change the image in each card. – Rohan Rao Oct 28 '19 at 05:26
  • @S.Stevens, about the bootstrap loader - I prefer the gif loader instead of bootstrap loader. And to be very honest I have no idea how to embed the bootstrap loader, so I am giving you the link. And also please see my Edit over the answer written. – Rohan Rao Oct 28 '19 at 05:35
  • Thanks so much for your help. I have nearly got it working now- just trying to get the gif to embed responsively. One thing I have just thought- the whole reason I wanted a loading gif was so that as the main image loads, the card remains the same size- I am now beginning to thing having to load another image before hand won't have fixed this issue... – S.Stevens Oct 28 '19 at 10:57
  • To have the dimension of card and loader to be of same height and width, you will need to apply CSS to your **card** class. – Rohan Rao Oct 28 '19 at 15:38
  • Ah I see, thank you. Is there a way to responsively set the size of the card, when the image isn't there? – S.Stevens Oct 28 '19 at 16:33
  • @S.Stevens, it would be very weird if you set the width of card to be of specific width. Let it's width and height be default (i.e. 100% - don't write it in your CSS, this will be automatically assumed by Bootstrap class). So even if there is no image, after loader , the size of the card won't alter. – Rohan Rao Oct 29 '19 at 13:23
  • Ah I see, what about before the loader image itself loads, as this was the problem I faced before. Thank you so much for all your help! – S.Stevens Oct 29 '19 at 13:43
  • If you have the image, the card won't collapse. Make sure you give the exact path of your image. – Rohan Rao Oct 29 '19 at 14:39
  • Ok, I'll try this and let you know. If this is the case I may not need the loader at all. Could it be that I am using an online placeholder tool? It just seems odd for the card to collapse before its loaded. – S.Stevens Oct 29 '19 at 15:10
  • @S.Stevens You are welcome! :) And about the loader case whether to keep or not - it totally depends what is your requirement.It may be possible that your above mentioned requirement get changed in future. Using Online placeholder tool would not be a solution as it would requirement too much of code and may other libraries. When you are designing something, make sure it is optimal for you as a developer as well as for the user. – Rohan Rao Oct 30 '19 at 05:43