estilizando_um_component - VWJavascript/Alurapic GitHub Wiki

Estilizando um componente

Excelente, já conseguimos cadastrar fotos, inclusive aprendemos a validar nosso formulário. Porém, eu trabalho com um designer que teve uma excelente ideia: colocar uma sombra no painel de cada imagem, inclusive realizar um zoom na imagem do painel quando passarmos o mouse sobre ela. Por mais que eu utilize o bootstrap, coisas específicas como essa eu precisarei implementar.

Vamos começar estilizando nosso painel. Que tal eu criar um arquivo CSS específico para esse componente? E que tal eu salvá-lo dentro da mesma pasta do componente? Dessa maneira, quando olharmos a pasta do componente saberemos com clareza onde está a sua folha de estilo.

Vamos o criar arquivo alurapic/client/app/painel/painel.component.css com o seguinte estilo:

// alurapic/client/app/painel/painel.component.css
.efeito {

    box-shadow: 2px 2px 15px;
}

E claro, precisamos alterar nosso template adicionando a classe efeito na div do nosso painel:

// alurapic/client/app/painel/painel.component.html

<div class="panel panel-default efeito">
    <div class="panel-heading">
        <h3 class="panel-title text-center">{{titulo}}</h3>
    </div>
    <div class="panel-body">
        <ng-content></ng-content>
    </div>
</div>

E também não podemos nos esquecer de importarmos o arquivo css que criamos no head da nossa página index.html:

<!-- alurapic/client/index.html -->
<!doctype html>
<html>
    <head>
        <base href="/">
        <title>Alurapic</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">

        <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
        <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap-theme.min.css">

        <!-- importando novo CSS -->
        <link rel="stylesheet" href="app/painel/painel.component.css">

Perfeito! Quando recarregamos a página temos nosso painel sombreado:

image

Vamos resolver agora o problema da nossa foto criando o arquivo alurapic/client/app/foto/foto.component.css com o estilo que realiza o zoom da imagem através do ponteiro do mouse:

/* alurapic/client/app/foto/foto.component.css */

.efeito:hover {
    transition: all 0.5s;
    transform: scale(1.15);
}

.efeito {
    transition: all 1s;
}

E novamente, precisamos lembrar de importá-lo em nossa página:

<!-- alurapic/client/index.html -->
<!doctype html>
<html>
    <head>
        <base href="/">
        <title>Alurapic</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">

        <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
        <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap-theme.min.css">

        <link rel="stylesheet" href="app/painel/painel.component.css">
        <link rel="stylesheet" href="app/foto/foto.component.css">

Adicionando a classe no template do nosso componente:

<!-- alurapic/client/app/foto/foto.component.html -->
<img class="img-responsive center-block efeito" src="{{url}}" alt="{{titulo}}">

O problema de estilos globais

Pronto, tudo certo. Agora vamos recarregar nossa página e ver o resultado. Espere um pouco! Temos um problema! Nosso painel e foto ganham a sombra, inclusive o painel também cresce quando passamos o mouse por cima, não apenas a foto! O problema é que cada componente possui a classe efeito e como usamos o mesmo seletor CSS para criar efeitos diferentes, os dois são aplicados. Podemos resolver isso qualificando nosso seletor:

/* alurapic/client/app/painel/painel.component.css */

.painel.efeito {
    box-shadow: 2px 2px 15px;
}

Adicionando a classe painel:

// alurapic/client/app/painel/painel.component.html

<div class="panel panel-default painel efeito">
    <div class="panel-heading">
        <h3 class="panel-title text-center">{{titulo}}</h3>
    </div>
    <div class="panel-body">
        <ng-content></ng-content>
    </div>
</div>
/* alurapic/client/app/foto/foto.component.css */

.foto.efeito:hover {
    transition: all 0.5s;
    transform: scale(1.15);
}

.foto.efeito {
    transition: all 1s;
}

Adicionando a classe foto:

<!-- alurapic/client/app/foto/foto.component.html -->
<img class="img-responsive center-block foto efeito" src="{{url}}" alt="{{titulo}}">

image

O problema é que nossos estilos possuem um escopo global, aplicados em qualquer elemento de nossa página que faça uso das nossas classes. Essa grande vantagem do CSS pode se tornar uma dor de cabeça, quando queremos que um estilo seja aplicado em um elemento da nossa página apenas. Por mais que qualifiquemos nossos seletores nada impede que o mesmo seletor qualificado já esteja sendo usado em outro arquivo CSS que muitas vezes sequer podemos alterar.

Uma solução para esse problema seria reduzir o escopo do estilo de um componente ao próprio componente e não à página como um todo. Com isso, poderíamos usar nosso componente em qualquer lugar da aplicação sem termos que nos preocupar com a colisão de seletores ou termos que qualificar todos eles. A boa notícia é que os componentes do Angular permitem a aplicação de estilos que tem como escopo o próprio elemento que estilizam.

Primeiro, vamos remover as importações de painel.component.css e foto.component.css de index.html:

<!-- REMOVER OS DOIS CSS'S ABAIXO -->
<link rel="stylesheet" href="app/painel/painel.component.css">
<link rel="stylesheet" href="app/foto/foto.component.css">

Segundo, vamos remover as classes painel e foto dos arquivos CSS, inclusive da marcação HTML:

/* alurapic/client/app/painel/painel.component.css */

.efeito {
    box-shadow: 2px 2px 15px;
}

Removendo a classe painel:

// alurapic/client/app/painel/painel.component.html

<div class="panel panel-default efeito">
    <div class="panel-heading">
        <h3 class="panel-title text-center">{{titulo}}</h3>
    </div>
    <div class="panel-body">
        <ng-content></ng-content>
    </div>
</div>
/* alurapic/client/app/foto/foto.component.css */

.efeito:hover {
    transition: all 0.5s;
    transform: scale(1.15);
}

.efeito {
    transition: all 1s;
}

Removendo a classe foto:

<!-- alurapic/client/app/foto/foto.component.html -->
<img class="img-responsive center-block efeito" src="{{url}}" alt="{{titulo}}">
⚠️ **GitHub.com Fallback** ⚠️