Tudo sobre Tecnologia da Informação

Dicas de FlexBox Parte 2

Nós podemos controlar o tamanho máximo dos itens com a propriedade flex-basis, no caso, o container deverá está com flex-flow: row nowrap. O valor padrão do flex-basis é auto, que a largura de cada item é o tamanho do conteúdo, ao diminuir o container ele espremerá os itens ao máximo, mas se aumentar muito ele não espichará todos os itens. Podemos colocar no flex-basis um tamanho como 200px, mas nesse caso ele não se adaptará ao conteúdo e todos os itens terão esse tamanho fixo, independente do conteúdo dos mesmos, mas poderão ser esprimidos também. Os itens podem cada um ter um tamanho definido também, mesmo diferentes. No caso de Flexbox é melhor usar o flex-basis do que o width ou height.

Deixe os itens de A a G no HTML e o CSS assim:


div.container {
    background-color: lightsalmon;
    display: flex;
    flex-flow: row nowrap;
}

div.item {
    background-color: lightskyblue;
    border: 1px solid black;
    text-align: center;
    flex-basis: auto;
}

No lugar da letra de alguns dos itens, coloque um texto maior. Depois tente mudar o valor de flex-basis do item assim:


flex-basis: 150px;

Tente espremer os conteúdos.

Ao colocar no container o flex-flow: row wrap, ele quebrará ao chegar no limite, ao invés de espremer.

Podemos também controlar o tamanho dos itens, com flex-grow e flex-shrink, sendo que grow significa crescer e shrink significa diminuir. Nesse caso usaremos no container o valor nowrap no flex-flow. O valor padrão de flex-grow é 0 e o flex-shrink é 1 (ou seja, não pode crescer e pode encolher, veja o 1 como true e 0 como false). Para os itens ficarem totalmente elásticos (que crescem e aumentam quanto precisar, coloque os dois como 1.

Deixe o HTML assim:


<div class="container">
    <div class="item">A</div>
    <div class="item">B</div>
    <div class="item">C</div>
</div>

Com esse CSS:


div.container {
    background-color: lightsalmon;
    display: flex;
    flex-flow: row nowrap;
}

div.item {
    background-color: lightskyblue;
    border: 1px solid black;
    text-align: center;
    flex-basis: 250px;
}

Veja que, por padrão, ele não estica, mas encolhe. Coloque isso no CSS do item:


flex-shrink: 0;

Aí ele não vai mais encolher, e também não vai quebrar por causa da configuração nowrap no container. Para ele encolher, coloque acima o valor 1. Depois deixe o flex-grow assim, no item:


flex-shrink: 1;
flex-grow: 0;

Pra ele ficar totalmente elástico, coloque o valor 1 em ambos acima.

PS: O flex-grow não funciona só com nowrap, podemos fazer a configuração assim, por exemplo:


div.container {
    background-color: lightsalmon;
    display: flex;
    flex-flow: row wrap;
}

div.item {
    background-color: lightskyblue;
    border: 1px solid black;
    text-align: center;
    flex-basis: 250px;
    flex-shrink: 1;
    flex-grow: 1;
}

No caso acima, ele vai quebrar normalmente os itens, que podem ser encolhidos ou esticados. Mas o ideal no caso acima é deixar nowrap no container.

Teste colocando, no lugar das letras, textos longos, como o famoso lorem.

As propriedades do flex-shrink e flex-grow não são apenas 0 e 1, podemos, por exemplo, colocar um flex-grow em cada um dos três itens, com os valores 0, 1 e 0. No caso só o do meio crescerá. Num segundo exemplo, teremos os valores 0, 1 e 2, o 0 não estica, o 1 esticará e o 2 esticará o dobro do 1. Mas se nos três exemplos, tivermos 0, 2 e 2, os dois crescerão igual (não o dobro de nada), pois segue a proporção (1 pra 2 é o mesmo que 2 pra 4 ou 3 pra 6).

Da mesma forma, podemos exemplificar com flex-shrink, de forma parecida. Os três itens com valores 0, 1 e 0, apenas o do meio (com 1) encolherá. Se usarmos o exemplo com 2, 0 e 1, o 2 reduzirá o dobro de 1 e o 0 ficará fixo. Da mesma forma, segue proporções (1 pra 2 é igual 2 pra 4 ou 3 pra 6).

PS: Lembrando que as proporções funcionam com valores maiores ou iguais à 1. De 0 pra 1 é o mesmo que 0 pra 4, por exemplo. Sempre trabalhe com proporções como 1 pra 2, 2 pra 4, etc.

Podemos também misturar ambas as propriedades. Lembre-se do exemplo da forma da água. Veja um exemplo disso:

Flex Grow Shrink

Para exemplificar, deixe os itens em HTML assim:


<div class="container">
    <div class="item" id="cxA">A</div>
    <div class="item" id="cxB">B</div>
    <div class="item" id="cxC">C</div>
</div>

E o CSS assim:


div.container {
    background-color: lightsalmon;
    display: flex;
    flex-flow: row nowrap;
}

div.item {
    background-color: lightskyblue;
    border: 1px solid black;
    text-align: center;
    flex-basis: 150px;
}

div#cxA {
    flex-shrink: 0;
    flex-grow: 0;
}

div#cxB {
    flex-shrink: 0;
    flex-grow: 0;
}

div#cxC {
    flex-shrink: 0;
    flex-grow: 0;
}

Aí, poderemos brincar um pouco com as duas propriedades:


div#cxA {
    flex-shrink: 1;
    flex-grow: 0;
}

div#cxB {
    flex-shrink: 0;
    flex-grow: 2;
}

div#cxC {
    flex-shrink: 2;
    flex-grow: 1;
}

A propriedade flex se aplica aos itens, e é uma forma de simplificar o uso de flex-grow, flex-shrink e flex-basis, que aliás, é o recomendado, sempre nessa ordem, veja um exemplo abaixo:

Flex

Deixe o CSS assim:


div.container {
    background-color: lightsalmon;
    display: flex;
    flex-flow: row nowrap;
}

div.item {
    background-color: lightskyblue;
    border: 1px solid black;
    text-align: center;
}

div#cxA {
    flex-shrink: 1;
    flex-grow: 0;
    flex-basis: 150px;
}

div#cxB {
    flex-shrink: 0;
    flex-grow: 2;
    flex-basis: 150px;
}

div#cxC {
    flex-shrink: 2;
    flex-grow: 1;
    flex-basis: 150px;
}

Aí, simplificando:


div#cxA {
    flex: 0 1 150px;
}

div#cxB {
    flex: 2 0 150px;
}

div#cxC {
    flex: 1 2 150px;
}

Em outras palavras, o flex é a união de flex-grow, flex-shrink e flex-basis, nessa ordem. O valor padrão dele é 0 1 auto, pode estar flex: initial também, que é a mesma coisa. Para não deixar nada flexível use 0 0 auto ou flex: none. Para deixar ele totalmente elástico use 1 1 auto ou apenas flex: auto. Se colocarmos um valor só, como flex: 3, ele só definirá o grow (seria o mesmo que 3 1 auto, com os dois últimos sendo os padrões).

Para exercitarmos tudo isso, faremos um menu. Este é o HTML básico da página:


<header>
    <h1>Meu Site</h1>

    <nav>
        <a href="#">Opção 1</a>
        <a href="#">Opção 2</a>
        <a href="#">Opção 3</a>
        <a href="#">Opção 4</a>
        <a href="#">Opção 5</a>
        <a href="#">Opção 6</a>
    </nav>
</header>
<main>
    <h2>Teste de FlexBox</h2>

    <p>Exemplo de parágrafo (coloque o lorem aqui).</p>

    <p>Exemplo de parágrafo (coloque o lorem aqui).</p>
</main>

Com esse CSS:


* {
    margin: 0px;
    padding: 0px;
    box-sizing: border-box;
}

Deixe o CSS depois assim:


* {
    margin: 0px;
    padding: 0px;
    box-sizing: border-box;
}

body {
    font-family: Arial, sans-serif;
    font-size: 1em;
    background-color: lightgray;
    height: 100vh;
    width: 100vw;
}

header {
    background-color: gray;
    color: white;
    padding: 10px;
}

header > h1 {
    border: 1px dotted black;
}

header > nav {
    border: 1px dotted black;
}

header > nav > a {
    background-color: black;
    color: white;
    padding: 10px;
    margin: 5px;
    border-radius: 5px;
    text-decoration: none;
    text-align: center;
}

header > nav > a:hover {
    background-color: white;
    color: black;
    transition: background-color .5s;
}

main {
    background-color: white;
    margin: 10px;
    padding: 10px;
    border-radius: 10px;
    box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.3);
}

PS: Os border com dotted devem ser retirados depois, é só pra termos uma ideia da delimitação de cada bloco/tag.

Vamos fazer o header como nosso container, e os itens seria o h1 e o nav (os links a não contam). Deixe a parte do CSS do header assim:


header {
    background-color: gray;
    color: white;
    padding: 10px;
    display: flex;
    flex-flow: row wrap;
    justify-content: space-between;
    align-items: center;
}

Deixe o do h1 e do nav assim, que também será um container (sim, podemos ter um container FlexBox dentro do outro):


header > h1 {
    border: 1px dotted black;
    flex: 0 0 200px;
}

header > nav {
    border: 1px dotted black;
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-end;
}

Podemos adicionar os conceitos de medias queries para deixar ele mais responsivo. Adicione no HTML esse link:


<link rel="stylesheet" href="css/mobile.css" media="screen and (max-width: 575px)"/>

E coloque no arquivo criado (mobile.css) esse código aqui, só pra testar:


@charset "UTF-8";

body {
    background-color: red;
}

Depois, caso já esteja funcionando, apague esse red e deixe o código assim:


header, header > nav {
    flex-flow: column nowrap;
}

header > h1 {
    flex-basis: 50px;
}

header > nav > a {
    width: 95vw;
}

Depois disso, retire os pontilhados (os borders com dotted) do arquivo principal de estilo, e neste, podemos ainda, por exemplo, colocar uma sombra no texto do h1:


header > h1 {
    /* border: 1px dotted black; */
    flex: 0 0 200px;
    text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.4);
}

PS: Podemos colocar o ícone do hamburguinho pra ocultar e mostrar o menu no mobile também.

Vamos fazer um novo projeto, com esse HTML de exemplo:


<header class="normal">
    <h1>Exemplo de Conteúdo Flexível</h1>

    <p>Conteúdo de texto (coloque um lorem).</p>
</header>
<main>
    <section class="flex-content">
        <!-- Os dois vêm o texto primeiro e a mídia depois,
         mas eles serão quebrados de formas diferentes. -->
        <article class="media-text">
            <div class="text">
                <h2>Elemento Media-&gt;Text</h2>

                <p>Conteúdo de texto (coloque um lorem).</p>
            </div>
            <div class="media">
                <img src="imagem/imagem.png" alt="Minha Imagem"/>
            </div>
        </article>
        <article class="text-media">
            <div class="text">
                <h2>Elemento Text-&gt;Media</h2>

                <p>Conteúdo de texto (coloque um lorem).</p>
            </div>
            <div class="media">
                <iframe width="560" height="315" src="https://www.youtube.com/embed/VBGMnFHRqcY"></iframe>
            </div>
        </article>
    </section>
    <section class="normal">
        <h2>Conteúdo Normal</h2>

        <p>Conteúdo de texto (coloque um lorem).</p>
    </section>
</main>

Com esse CSS:


* {
    margin: 0px;
    padding: 0px;
    box-sizing: border-box;
}

body {
    font-family: Arial, sans-serif;
    font-size: 1em;
    line-height: 1.5em;
}

p {
    margin-bottom: 10px;
    text-align: justify;
}

h1, h2 {
    margin-bottom: 20px;
    line-height: 1.2em;
    text-align: left;
}

header, section.normal {
    padding: 20px;
}

section.flex-content {
    padding: 20px;
    background-color: rgb(156, 156, 156);
}

As partes de cima e de baixo do site não serão flexíveis, apenas o que está no meio (com a classe flex-content).

Faça esse código só pra vermos a divisão de artigos do site, depois retire isso:


section > article {
    border: 2px dashed green;
}

Faremos um container dentro de outro (no caso, o article dentro de section, coloque isso no CSS:


section.flex-content {
    padding: 20px;
    background-color: rgb(156, 156, 156);
    display: flex;
    flex-flow: column nowrap;
}

article.text-media {
    display: flex;
    flex-flow: row wrap;
}

article.media-text {
    display: flex;
    flex-flow: row wrap-reverse;
}

article > div.text {
    flex: 1 1 500px;
    border: 2px dashed blue;
}

article > div.media {
    flex: 1 0 400px;
    border: 2px dashed red;
}

Deixe o CSS dos article assim:


article.text-media {
    display: flex;
    flex-flow: row wrap;
    justify-content: space-between;
}

article.media-text {
    display: flex;
    flex-flow: row wrap-reverse;
    justify-content: space-between;
}

Coloque essas configurações pras divs de media, pra ele as centralizar:


div.media > img {
    display: block;
    margin: auto;
    padding: 10px;
    width: 300px;
}

div.media > iframe {
    display: block;
    margin: auto;
    padding: 0px 20px;
    width: 90%;
}

Agora retire todos os pontilhados com dashed.

PS: Podemos usar o site Flexbox Froggy pra praticar o uso de Flexbox, o link do site é esse: https://flexboxfroggy.com/

Parte 1 da Matéria