DEV Community

Cover image for Cards responsivos sem altura fixa e carrossel de cards com CSS e Glide.js
Laura
Laura

Posted on

Cards responsivos sem altura fixa e carrossel de cards com CSS e Glide.js

Cover image
Photo by Pixabay: https://www.pexels.com/photo/close-up-of-text-on-black-background-256502/


A ideia aqui por trás é construir um set de cards responsivos sem que seja necessário definir uma altura fixa para cada card e também flexível ao tamanho que cada elemento do card irá assumir.

O foco não será na estilização mas sim na construção da responsividade dos elementos e do card em si.

No fim, será possível incluir os cards no carrossel do Glide.js, deixando-os responsivos também.

PASSO 1: criar o card

Crie um container que irá guardar o conteúdo do card e um wrapper do conteúdo.

<div class="card">
    <div class="card-content">

    </div>
</div>
Enter fullscreen mode Exit fullscreen mode
.card {
    display: flex;
    border: 1px solid black;
}

.card-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Queremos que os elementos possam crescer ou encolher conforme necessário, por esse motivo o card-content terá um flex: 1 (flex-grow: 1, flex-shrink: 1, flex-basis: 0%).

PASSO 2: criar o conteúdo do card

Dentro do card-content teremos uma imagem com uma caption, e as informações

<div class="card">
    <div class="card-content">
        <figure>
            <div class="img-container"><img src="image.jpg" alt="Pessoa debaixo de guarda-chuva caminhando em rua do Japão"></div>
            <figcaption>
                Image by <a href="https://pixabay.com/users/masashiwakui-4385858/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2014619">Masashi Wakui</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2014619">Pixabay</a>
            </figcaption>
        </figure>
        <div class="card-bottom">
            <span class="card-category">CATEGORIA</span>
            <h2 class="card-title">ESSE É O TÍTULO DO CARD</h2>
            <div style="margin-top: auto;">
                <span class="card-desc">essa é uma descrição</span>
                <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
            </div>
        </div>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode
.img-container {
    width: 100%;
    height: 250px;
}

figure {
    margin: 0;
    padding: 0;
    margin-bottom: 10px;
}

img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card-bottom {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 5px;
}

.card-title {
    background-color: aquamarine;
}

.btn-container {
    margin-top: 10px;
}
Enter fullscreen mode Exit fullscreen mode

O card-bottom também terá um flex:1, visto que os elementos precisam ter flexibilidade.

No caso desse exemplo, o elemento que queremos que fique na mesma linha em todos os cards é o que está servindo de container para a descrição e o botão, por esse motivo, sua margin-top está definida como auto.

<div style="margin-top: auto;">
    <span class="card-desc">essa é uma descrição</span>
    <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
</div>
Enter fullscreen mode Exit fullscreen mode

E essa é a ideia, não importando o elemento no qual queremos que esteja na mesma linha em todos os cards, queremos que tenha essa “conversação” entre eles, senão, ficariam todos desalinhados conforme imagem abaixo:

2 cards inline com elementos desalinhados

E na verdade queremos que fiquem alinhados, conforme imagem abaixo:

2 cards inline com as partes inferiores alinhadas

Podemos notar que a categoria e o título continuam desalinhados, isso porque como falado anteriormente, é necessário definir a margin-auto do elemento que deseja alinhar. Nesse caso, podemos definir uma margin-bottom:auto para a categoria, obtendo assim, o alinhamento desejado:

2 cards inline com os elementos de categoria também alinhados

Agora é possível ver que tanto a categoria, como o título, como os demais, estão todos alinhados.

Essa é uma forma de criar cards alinhados entre si, sem precisar definir valores fixos. Portanto, nossos elementos conseguem ter sua flexibilidade e ao mesmo tempo ter o mesmo aspecto do card ao seu lado.

PASSO 3: construção do carrossel com Glide.js

Como estamos utilizando HTML e CSS básicos, iremos incluir as dependênicas do Glide.js por meio do cdnjs.

CSS:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.6.0/css/glide.core.min.css" integrity="sha512-tYKqO78H3mRRCHa75fms1gBvGlANz0JxjN6fVrMBvWL+vOOy200npwJ69OBl9XEsTu3yVUvZNrdWFIIrIf8FLg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
Enter fullscreen mode Exit fullscreen mode

Script:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.6.0/glide.min.js" integrity="sha512-2sI5N95oT62ughlApCe/8zL9bQAXKsPPtZZI2KE3dznuZ8HpE2gTMHYzyVN7OoSPJCM1k9ZkhcCo3FvOirIr2A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Enter fullscreen mode Exit fullscreen mode

Anteriormente, tínhamos um container para os cards, porém agora iremos utilizar o layout do carrossel do Glide:

<div class="glide">
        <div class="glide__track" data-glide-el="track">
            <ul class="glide__slides">
                <li class="glide__slide">
                    <div class="card">
                        <div class="card-content">
                            <figure>
                                <div class="img-container"><img src="image.jpg" alt="Pessoa debaixo de guarda-chuva caminhando em rua do Japão"></div>
                                <figcaption>
                                    Image by <a href="https://pixabay.com/users/masashiwakui-4385858/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2014619">Masashi Wakui</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2014619">Pixabay</a>
                                </figcaption>
                            </figure>
                            <div class="card-bottom">
                                <span class="card-category">CATEGORIA</span>
                                <h2 class="card-title">ESSE É O TÍTULO DO CARD</h2>
                                <div style="margin-top: auto;">
                                    <span class="card-desc">essa é uma descrição</span>
                                    <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </li>
                <li class="glide__slide">
                    <div class="card">
                        <div class="card-content">
                            <figure>
                                <div class="img-container"><img src="image2.jpg" alt="Monumento sobre a água"></div>
                                <figcaption>
                                    Image by <a href="https://pixabay.com/users/jordymeow-943760/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1976609">Jordy Meow</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1976609">Pixabay</a>
                                </figcaption>
                            </figure>
                            <div class="card-bottom">
                                <span class="card-category">ESSA É UMA CATEGORIA COM UM NOME BEM LONGO</span>
                                <h2 class="card-title">ESSE É O TÍTULO DO CARD SÓ QUE UM POUCO MAIOR</h2>
                                <div style="margin-top: auto;">
                                    <span class="card-desc">essa é uma descrição</span>
                                    <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </li>
                <li class="glide__slide">
                    <div class="card">
                        <div class="card-content">
                            <figure>
                                <div class="img-container"><img src="image3.jpg" alt="Flores"></div>
                                <figcaption>
                                    Image by <a href="https://pixabay.com/users/shell_ghostcage-2016503/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2218771">For commercial use, some photos need attention.</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2218771">Pixabay</a>
                                </figcaption>
                            </figure>
                            <div class="card-bottom">
                                <span class="card-category">CATEGORIA</span>
                                <h2 class="card-title">ESSE É O TÍTULO DO CARD</h2>
                                <div style="margin-top: auto;">
                                    <span class="card-desc">essa é uma descrição</span>
                                    <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </li>
            </ul>
        </div>
        <div class="glide__arrows" data-glide-el="controls">
            <button class="glide__arrow glide__arrow--left" data-glide-dir="<">prev</button>
            <button class="glide__arrow glide__arrow--right" data-glide-dir=">">next</button>
          </div>
    </div>
Enter fullscreen mode Exit fullscreen mode

Precisaremos também inicializar ele:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.6.0/glide.min.js" integrity="sha512-2sI5N95oT62ughlApCe/8zL9bQAXKsPPtZZI2KE3dznuZ8HpE2gTMHYzyVN7OoSPJCM1k9ZkhcCo3FvOirIr2A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
    const glide = new Glide('.glide', {
        type: 'carousel',
        perView: 2,
        autoplay: 1500,
        gap: 15,
        breakpoints: {
            991.1: {
                perView: 3
            },
            767.1: {
                perView: 2
            },
            480.1: {
                perView: 1
            }
        }
    })

    glide.mount()
</script>
Enter fullscreen mode Exit fullscreen mode

Link da documentação do Glide.js: https://glidejs.com/docs/setup/

Quando fizermos isso, veremos que a responsividade irá quebrar novamente, como segue imagem abaixo:

2 cards inline com elementos desalinhados

Para isso será necessário ajustar a altura do slide e a altura do card, da seguinte forma:

.card {
    display: flex;
    border: 1px solid black;
    height: 100%;
}

.glide__slide {
    height: auto !important;
}
Enter fullscreen mode Exit fullscreen mode

E assim obtemos novamente o resultado anterior:

2 cards inline com elementos alinhados

Segue código completo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./teste.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.6.0/css/glide.core.min.css" integrity="sha512-tYKqO78H3mRRCHa75fms1gBvGlANz0JxjN6fVrMBvWL+vOOy200npwJ69OBl9XEsTu3yVUvZNrdWFIIrIf8FLg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <title>Document</title>
</head>
<body>     
    <div class="glide">
        <div class="glide__track" data-glide-el="track">
            <ul class="glide__slides">
                <li class="glide__slide">
                    <div class="card">
                        <div class="card-content">
                            <figure>
                                <div class="img-container"><img src="image.jpg" alt="Pessoa debaixo de guarda-chuva caminhando em rua do Japão"></div>
                                <figcaption>
                                    Image by <a href="https://pixabay.com/users/masashiwakui-4385858/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2014619">Masashi Wakui</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2014619">Pixabay</a>
                                </figcaption>
                            </figure>
                            <div class="card-bottom">
                                <span class="card-category">CATEGORIA</span>
                                <h2 class="card-title">ESSE É O TÍTULO DO CARD</h2>
                                <div style="margin-top: auto;">
                                    <span class="card-desc">essa é uma descrição</span>
                                    <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </li>
                <li class="glide__slide">
                    <div class="card">
                        <div class="card-content">
                            <figure>
                                <div class="img-container"><img src="image2.jpg" alt="Monumento sobre a água"></div>
                                <figcaption>
                                    Image by <a href="https://pixabay.com/users/jordymeow-943760/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1976609">Jordy Meow</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1976609">Pixabay</a>
                                </figcaption>
                            </figure>
                            <div class="card-bottom">
                                <span class="card-category">ESSA É UMA CATEGORIA COM UM NOME BEM LONGO</span>
                                <h2 class="card-title">ESSE É O TÍTULO DO CARD SÓ QUE UM POUCO MAIOR</h2>
                                <div style="margin-top: auto;">
                                    <span class="card-desc">essa é uma descrição</span>
                                    <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </li>
                <li class="glide__slide">
                    <div class="card">
                        <div class="card-content">
                            <figure>
                                <div class="img-container"><img src="image3.jpg" alt="Flores"></div>
                                <figcaption>
                                    Image by <a href="https://pixabay.com/users/shell_ghostcage-2016503/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2218771">For commercial use, some photos need attention.</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2218771">Pixabay</a>
                                </figcaption>
                            </figure>
                            <div class="card-bottom">
                                <span class="card-category">CATEGORIA</span>
                                <h2 class="card-title">ESSE É O TÍTULO DO CARD</h2>
                                <div style="margin-top: auto;">
                                    <span class="card-desc">essa é uma descrição</span>
                                    <div class="btn-container"><button class="card-btn">Ver mais conteúdo</button></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </li>
            </ul>
        </div>
        <div class="glide__arrows" data-glide-el="controls">
            <button class="glide__arrow glide__arrow--left" data-glide-dir="<">prev</button>
            <button class="glide__arrow glide__arrow--right" data-glide-dir=">">next</button>
          </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.6.0/glide.min.js" integrity="sha512-2sI5N95oT62ughlApCe/8zL9bQAXKsPPtZZI2KE3dznuZ8HpE2gTMHYzyVN7OoSPJCM1k9ZkhcCo3FvOirIr2A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script type="text/javascript">
        const glide = new Glide('.glide', {
            type: 'carousel',
            perView: 2,
            autoplay: 1500,
            gap: 15,
            breakpoints: {
                991.1: {
                    perView: 3
                },
                767.1: {
                    perView: 2
                },
                480.1: {
                    perView: 1
                }
            }
        })

        glide.mount()
    </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
.cards-container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 10px;
}

.card {
    display: flex;
    border: 1px solid black;
    height: 100%;
}

.card-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    width: 100%;
}

.img-container {
    width: 100%;
    height: 250px;
}

figure {
    margin: 0;
    padding: 0;
    margin-bottom: 10px;
}

img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.card-bottom {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 5px;
}

.card-title {
    background-color: aquamarine;
}

.btn-container {
    margin-top: 10px;
}

.card-category {
    margin-bottom: auto;
}

.glide__arrows {
    margin-top: 10px;
}

.glide__slide {
    height: auto !important;
}
Enter fullscreen mode Exit fullscreen mode

Se você leu até aqui, obrigada :)

Top comments (0)