Colunas de Conteúdo
Implementação - Menus
Menus
Este artigo é a sétima parte do tutorial sobre Web Design com Flex Box Model.
Conteúdo
Finalmente chegamos à última parte deste tutorial. Vamos ver como implementar as colunas de conteúdo.
No site original adotado como exemplo, Social Media Template por W3Schools, em telas com 600 pixels ou mais, existem três colunas conforme imagem a seguir:
Nossa versão também tem três colunas na resolução máxima da tela, com divisão e
comportamento diferentes das do site original. A largura da coluna principal ocupa 50% do espaço
disponível, ficando cada uma das telas laterais com 25% deste espaço.
Abaixo de 768
pixels o site passa a ter apenas uma coluna, já que o espaço resultante é escasso.
O comportamento do site original, ao ter a tela diminuída abaixo dos 600 pixels, coloca a coluna esquerda na parte superior, a coluna central empilhada logo abaixo e ao fundo, antes do rodapé, a coluna da direita. O que faremos é alterar o ponto de corte de 600 pixels para 768 pixel, eliminando a etapa intermediária com duas colunas:
Esse comportamento já foi pré-configurado na parte 3 deste tutorial.
Arquivos
Como de praxe, copie os arquivos webLayout_00106.html, script_00106.js e style_00106.css renomeando-os como webLayout_00107.html, scritp_00107.js e style_00107.css respectivamente, mantendo-os nas pastas pertinentes, como mostra a figura.
Nota:
Ao baixar os arquivos da seção de 'Downloads', mantenha as cópias de acordo com o esquema acima.
Coluna Esquerda
A estrutura da coluna esquerda é composta por um flex-contêiner com quatro flex-items, a saber:
- Perfil do proprietário da página;
- Links para os seus grupos, eventos e fotos;
- Dados visuais mostrando os seus interesses;
- Quadro de notificações.
Vamos fazer a implementação desta coluna conforme sequência:
- Localize no arquivo webLayout_00107.html o trecho correspondente ao bloco "head" e altere o código conforme a linha em destaque abaixo, ou copie e cole o código que aparece na janela.
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../_css/style_00107.css">
<title>FlexBox Model for Social Media - Parte 7</title>
<link rel="stylesheet" href="../_font/fontawesome-free-5.12.1-web/css/all.css">
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
</head>
- Ainda no arquivo webLayout_00107, insira a estrutura para os contêiners:
<main>
<div id="leftColumn">
<p>Essa é a coluna da esquerda</p>
<div id=“profile”>
Profile
</div>
<div id=“activities”>
Activities
</div>
<div id=“interests”>
Interests
</div>
<div id=“notifications”>
Notifications
</div>
</div>
</main>
- Em seguida, faça as alterações mostradas abaixo no arquivo style_00107.css:
main{
display:flex;
border:1px solid black;
padding-top:0;
display:flex;
}
#leftColumn, #mainColumn, #rightColumn{
display:flex;
flex-direction:column;
border:1px solid black;
padding:10px;
}
#profile, #activities, #interests, #notifications{
border:1px solid black;
padding:0.25em;
}
@media screen and (max-width:48em){
main{flex-direction:column}
#leftColumn, #mainColumn, #rightColumn{
width:100%;
}
}
@media screen and (min-width:48.1em){
main{flex-direction:row}
#leftColumn{ width:25%}
#mainColumn{ width:50%}
#rightColumn{ width:25%}
}
Na figura acima, a formatação da esquerda corresponde à telas com largura igual ou superior a 768px. A da direita corresponde à telas com largura abaixo de 768px.
Perfil
Divisões estabelecidas, passamos a formatar a divisão 'Profile'.
São 4
itens:
- Título;
- Avatar;
- Separador horizontal;
- Ícones com indicações de dados pessoais.
O título é formado pela tag <h3> e a centralização no container é feita através do ajuste da propriedade 'justify-content:center;' e da definição da direção de exibição 'flex-direction:column':
HTML:
<div id=profile>
<p>profile</p>
<h3>My
Profile</h3>
</div>
CSS:
#profile{
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
}
A formatação do Avatar é feita primeiramente, através da definição de seu
tamanho, tendo o cuidado de manter a largura e a altura iguais. Aplicamos, então, uma borda com
raio de 50%, com isso a figura resulta em um círculo. A regra em CSS, 'round6', fica responsável
por essa formatação.
A linha de separação entre a figura e os dados pessoais é feita
através de uma declaração direta em HTML com uma cláusula 'style' especificando a sua largura em
relação ao contêiner (50%), posicionamento (center) e cor:
HTML:
<img class="round6"
src="../_fig/avatar3.png" alt="Avatar">
<hr
style="width:50%;text-align:center;margin:auto;color:lightblue;">
<span><br/></span>
CSS:
.round6{
width:6.5em;
height:6.5em;
border:1px solid black;
border-radius:50%;
margin-bottom:2em;
}
Os dados pessoais foram formatados através de uma lista ordenada. O detalhe nessa formatação é o emprego de <span> para a inserção dos ícones em conjunto com a fonte:
HTML:
< div
class="profData">
< ul
style="list-style-type:none;">
<li><span class="fas fa-pen"
style="color:blue;"><span style="font-family:Roboto; color:black;">
Designer,
UI<br/><br/></span></span></li>
...
</ul>
</div>
Note que o espaço antes da designição do dado, como em Designer, é efetiva. Sua eliminação fará com que o texto fique mais próximo do ícone.
Na regra CSS, chama a atenção a propriedade 'transform:translate(-1.5em, -0.5em'. Essa propriedade ajusta a localização de um item, no caso 'profdata', em X e em Y, Neste exemplo faz com que a descrição, texto e ícone, fiquem mais à esquerda e mais acima da tela.
CSS:
.profData{
border:1px solid black;
display:flex;
flex-direction:column;
align-self:flex-start;
justify-content:flex-start;
list-style-type:none;
transform:translate(-1.5em, -0.5em);
}
Atividades
O box de atividades engloba três botões:
- My Groups
- My Events
- My Photos
No arquivo HTML, acrescentamos em 'activities', as três divisões, como mostrado a seguir:
<div id="activities">
<div id=”groups”>
<p>Grupos</p>
</div>
<div id=”events”>
<p>Eventos</p>
</div>
<div id=”photos”>
<p>Fotos</p>
</div>
</div>
Para cada uma dessas opções, acrescentamos um botão contendo um ícone Awesome, seguido do texto correspondente. Altere o código como mostrado:
<div id=”groups”>
<p>Grupos</p>
<i class="fas fa-circle-notch"><span
style="font-family:Roboto;" > My
Groups</span></i>
</div>
<div id=”events”>
<p>Eventos</p>
<i class="fas fa-calendar-check"><span
style="font-family:Roboto;"> My Events
</span></i>
</div>
<div id=”photos”>
<p>Fotos</p>
<i class="fas fa-users"><span
style="font-family:Roboto;"> My
Photos</span></i>
</div>
Observe a utilização de dois espaços para fazer a separação entre o ícone e o texto. A especificação da família da fonte pode parecer estranha, já que em tese, poderíamos colocar o ‘style’ diretamente na divisão <i>, evitando o emprego da tag <span>:
<i class="fas fa-users" style="font-family:Roboto;"> My Photos</i>
Ao fazermos isso, no entanto, o ícone perde a referência resultando em um carácter não determinado, já que a fonte Awesome possui a propriedade ‘font-family’ própria e, ao eliminarmos o <span>, o valor dessa propriedade é sobrescrito.
O comportamento dos botões deve ser ajustado para reagir aos eventos típicos inerentes:
- Cor de fundo ao passar o mouse sobre o botão
- Cor de fundo ao clicar
- Cor do texto em função da cor de fundo
No arquivo HTML, atribuimos a classe 'btnAct' às divisões com id igual a 'groups'; 'events' e 'photos' que englobam os botões respectivos, e estipulamos o seu comportamento no arquivo em CSS.
<div id="groups" class="btnAct" >
<i class="fas fa-circle-notch"><span
style="font-family:Roboto;"> My Groups</span></i>
...
</div>
A regra principal define a cor de fundo inicial, a cor da fonte nesta situação e altera o ponteiro do mouse. O modificador 'hover' define a cor de fundo e do texto quando o mouse estiver sobre o botão:
.btnAct{
background-color:rgb(125, 151, 165);
cursor:pointer;
color:white;
}
.btnAct:hover{
background-color:rgb(204, 204, 204);
color:black;
}
O efeito sobre os botões é mostrado na figura a seguir:
Ativação dos Botões
Para que os botões se tornem ativos, temos que criar um mecanismo no HTML para
capturar o clicar do mouse e uma rotina em JS que aplique a ação correspondente.
O
mecanismo no HTML consiste no emprego da palavra chave 'onclick' associada à um nome de função e
à um parâmetro que identifica o botão acionado:
<div id="groups" class="btnAct"
onclik=myFunction(1) >
<i class="fas
fa-circle-notch"><span style="font-family:Roboto;"> My
Groups</span></i>
</div>
<div id="events" class="btnAct"
onclik=myFunction(2) >
<i class="fas
fa-circle-notch"><span style="font-family:Roboto;"> My
Events</span></i>
</div>
<div id="photos" class="btnAct"
onclik=myFunction(1) >
<i class="fas
fa-circle-notch"><span style="font-family:Roboto;"> My
Photos</span></i>
</div>
Para as opções 'My Groups' e 'My Events' a ação será a exibição de um bloco HTML contendo o texto correspondente. No exemplo, o texto exibido é 'Some text...' que deve ser substituído pelo usuário. Um segundo clique fará com que a exibição do texto desapareça:
Obtemos esse efeito através de três etapas:
- Acrescentando o bloco de texto no arquivo HTML
<div id="activities">
<div id="groups" class="btnAct" onclick=myFunction(1)>
<i class="fas fa-circle-notch"><span
style="font-family:Roboto;"> My Groups</span></i>
</div>
<div id="gText">
<p>Some text..</p>
</div>
<div id="events" class="btnAct" onclick=myFunction(2)>
<i class="fas fa-calendar-check"><span
style="font-family:Roboto;"> My Events</span></i>
</div>
<div id="eText">
<p>Some text..</p>
</div>
<div id="photos" class="btnAct" onclick=myFunction(3)>
<i class="fas fa-users"><span
style="font-family:Roboto;"> My Photos</span></i>
</div>
<div id="pText">
<p>Some text..</p>
</div>
</div>
- Atribuindo algumas propriedades aos blocos de texto, no arquivo CSS:
#gText{
display:none;
border:1px solid black;
background-color:white;
color:black;
padding:0.25em 0.25em 0.25em 1.0em;
}
#eText{
display:none;
border:1px solid black;
background-color:white;
color:black;
padding:0.25em 0.25em 0.25em 1.0em;
}
#pText{
display:none;
background-color:white;
color:black;
padding:0.25em;
}
Note que a propriedade 'display' está ajustada inicialmente para 'none'. Isso garante que os blocos não serão exibidos no carregamento da página.
- Criando uma função em JS no arquivo 'scritp_00107':
function myFunction (valor){
var x=valor
var
c1=' ';
console.log('Parâmetro=', x)
switch (x){
case 1:
c1=document.getElementById('gText').style.display
if (c1===''){ c1='none'}
console.log('Exibição tipo:', c1)
if (c1==='none'){
document.getElementById('gText').style.display='flex'
document.getElementById('groups').className='btnActive'
} else{
document.getElementById('gText').style.display='none'
document.getElementById('groups').className='btnAct'
};
break
case
2:
. . .
break
case
3:
. . .
break
}
}
Basicamente essa função recebe um parâmetro x que identifica o botão acionado. Passa, então, à verificar se a propriedade 'display' do bloco de texto correspondente está ativa, invertendo o valor da mesma, ou seja, se estiver visível, torna invisível e vice-versa.
Exibição das fotos
A exibição de imagens em HTML é feita através da tag 'img' e uma cláusula 'src'
que faz referência à URL do arquivo a ser exibido, que pode ser do tipo png, jpg, gif, svg, bmp
e algumas variações que podem ser vistas neste
link.
Uma segunda cláusula 'alt', de uso fortemente recomendado, traz um
texto alternativo para a imagem que é exibido caso a mesma não seja carregada por algum motivo.
Esse texto também é empregado em leitores de tela, para auxiliar pessoas com problemas
visuais.
O fragmento a seguir ilustra o emprego desta tag:
HTML
<div class="fotosA1">
<div class="fotosA2">
<img
src="../_img/photos/bharat-patil-_kPuQcU8C-A-unsplash.jpg" alt="Cidade a noite"
style="width:100%">
<p
class="figText">”Vietnam - de Doruk Yemenici no Unsplash“>
</div>
</div>
Antes de publicar uma imagem na WEB, que não seja de sua autoria, consulte as regras para a sua publicação. Algumas vezes a simples menção do autor basta, outras vezes a sua utilização só é permitida mediante pagamento. A imagem deste exemplo foi obtida no Unsplash e é de utilização livre, mesmo assim, mantivemos a referência ao autor e o link para o site de divulgação.
Como estamos utilizando o modelo 'FlexBox', temos que tomar alguns cuidados para que as imagens sejam exibidas corretamente:
- As fotos serão exibidas em linhas contendo até 3 imagens;
- O texto explicativo será do tipo flex-item;
- As linhas com as fotos serão dispostas umas sobre as outras, em coluna.
Para obtermos esse comportamento, criamos duas classes:‘fotosA1’ e ‘fotosA2’. Em ‘fotosA1’ definimos um ‘flex-container’ ordenado em linha:
Em seguida, aplicamos a regra ‘flex-wrap=wrap’. Com isso, as imagens não poderão ter largura menor que a largura especificada por 'width'. Inicialmente essa largura é de 50% do espaço disponível no ‘flex-container’ estabelecida na regra ‘fotosA2’:
CSS
.fotosA1{
display:flex;
border:1px solid rgb(167, 156, 156);
padding:2px;
background-color:white;
margin:1.5%;
flex-basis:100%;
flex-wrap:wrap;
}
.fotosA2{
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
border:1px solid gray;
padding:0.25em;
width:50%;
}
Note que ‘fotosA2’ tem que ter ‘flex-direction=column’ para fazer com que os títulos explanativos aparecem abaixo da foto, caso contrário, apareceriam ao lado.
Bloco Interests
O bloco ‘interests’ é composto pela exibição de caixas de textos que, aparentemente, indicam a hierarquia do interesse do dono da página em função da cor e da posição no bloco. Não possui links e não são botões.
A implementação é feita em dois níveis de divisões. A primeira divisão, 'interests', envolve as outras divisões em uma moldura, criando um espaço próprio. A moldura também é aplicada às demais divisões:
HTML
<div id="interests">
<div id="iTitle">Interests</div>
<div>News</div>
<div>W3Schools</div>
<div>Labels</div>
<div>Games</div>
<div>Friends</div>
<div>Food</div>
<div>Design</div>
<div>Art</div>
<div>Photos</div>
</div>
#interests{
display:flex;
border:1px solid lightblue;
box-shadow:2px 2px 1px lightgray;
border-radius:4px;
padding:0;
margin:0;
width:100%;
}
Em um primeiro momento, as divisões aparecem em linha. Para conseguir o efeito desejado, aplicamos regras específicas à cada subdivisão:
O primeiro problema a ser solucionado é a disposição dos elementos em forma de coluna, para isso, alteramos a propriedade padrão ‘flex-direction’ para column:
CSS
#interests{
display:flex;
flex-direction:column;
border:1px solid lightblue;
box-shadow:2px 2px 1px lightgray;
border-radius:4px;
padding:0;
margin:0;
width:100%;
}
O segundo problema que temos que resolver, é a disposição de divisões por linha. Isso é feito alterando-se a propriedade padrão ‘flex-wrap’ de um ‘flex-container’, para ‘wrap’. Com isso, os itens irão se acomodar em uma divisão conforme a largura da mesma permitir.
CSS
#interests{
display:flex;
flex-direction:column;
flex-wrap:wrap;
border:1px solid lightblue;
box-shadow:2px 2px 1px lightgray;
border-radius:4px;
padding:0;
margin:0;
width:100%;
}
As propriedades de cada divisão é ajustada por regras CSS:
CSS
#i01,#i02,#i03,#i04,#i05,#i06,
#i07,#i08,#i09{
padding:0.5em;
flex-direction:column;
margin:0.25em;
border:1px solid black;
}
#i01{
background-color:rgb(48,62,69);
color:white;
}
#i02{
background-color:rgb(58, 75, 83);
color:white;
}
...
#i09{
background-color:rgb(223, 229, 232);
color:black;
}
Finalizamos o bloco com a formatação de seu título:
CSS
#iTitle{
display:flex;
flex-basis:100%;
justify-content:center;
font-size:1.2em;
font-weight:bold;
padding:0.5em;
}
Bloco Notificações
Este é o último bloco da coluna esquerda. A única ação é mostrar um texto
pré-formatado e possibilitar o fechamento do mesmo, tornando-o invisível. Em um site real, a
informação deve ser carregada de um servidor, o que foge do escopo deste tutorial, como também da página original em w3Schools.
Para a ação proposta, o mais relevante é a apresentação da possibilidade de se utilizar o ‘onclick’ diretamente no HTML, fazendo com que o box se esconda. O problema com essa solução é a impossibilidade de reativação da visualização, a não ser através do recarregamento da página.
Como observação, se no lugar de ‘style.display=none’ colocarmos ‘style.visibility=hidden’, o elemento seria oculto mas continuaria a ocupar a posição como se fosse exibido. Veja a diferença ao lado.
HTML:
<div id="notifications">
<div class="btnRight" onclick="this.parentElement.style.display = 'none'">
<div class="btnTxt">
<p>Hey!</p>
</div>
<div class="icon">
<i class="fas fa-times"></i>
</div>
<div>
<p>People are looking at your profile. find out who.</p>
</div>
CSS:
#notifications{
display:flex;
flex-direction:column;
border:1px solid lightblue;
box-shadow:2px 2px 1px lightgray;
border-radius:4px;
padding:0 ;
margin:0.5em 0 0 0;
padding-left:1.0em;
background-color:rgb(223,229,232);
width:100%;
}
.btnRight{
display:flex;
flex-direction:row;
justify-content:space-between;
}
.icon{
width:3em;
border:1px solid lightblue;
border-radius:4px;
box-shadow:2px 2px 1px lightgray;
background-color:rgb(190,203,210);
}
.icon:hover{
background:rgb(204,204,204);
}
.btnTxt{
font-weight:bolder;
}
Coluna Central
A coluna central é composta por dois tipos de elementos:um box editável, onde o usuário poderá colocar algum tipo de comentário, e um bloco com as postagens já feitas.
Os ‘posts’ existentes obedecem à formatação única do bloco, empilhando-se uns
sobre os outros, repetindo exatamente a mesma estrutura. Essa técnica facilita muito o trabalho
de manutenção e projeto de pré-formatação desses ‘posts’, que tem que ser automatizado e
carregado pelo servidor.
Os últimos blocos da coluna contém um box para aceitar ou recusar novas
amizades, um local (vazio) destinado à propaganda e um box com o ícone de um ‘bug’,
provavelmente para exibir alguma mensagem de erro ou coisa assim.
Implementação
Como já vimos anteriormente, precisamos definir um ‘flex-container’ que irá ‘empilhar’ todos esses blocos, deste modo a orientação deve ser do tipo ‘column’:
HTML
<div id="mainColumn">
<p>Essa é a coluna
principal</p>
<div
id=”newPost”>
<p>Novas
postagens</p>
</div>
<div class=”post”>
<p>Postagens</p>
</div>
<div id=”ads”>
<p>Propagandas</p>
</div>
<div id=”bug”>
<p>Bugs</p>
</div>
</div>
Observe que, para blocos repetitivos, ao invés de utilizarmos um ‘id’ é conveniente utilizarmos uma classe, já que os ‘ids’ são únicos e as classes podem ser utilizadas por tantos blocos quanto quizermos. Para facilitar a visualização, vamos definir uma borda ao redor dos elementos.
CSS
#mainColumn{
flex-basis:50%;
flex-direction:column;
}
#newPost, #bug,
#ads{
border:1px solid
black;
padding:1em;
}
.post{
border:1px
solid black;
padding:1em;
}
Para o bloco de novas postagens, temos que definir um elemento editável em HTML, ou seja, um elemento na página que pode ser editado pelo leitor. Isso é feito através da cláusula 'contenteditable' colocado na tag 'p'.
<div id="newPost">
<h5>Based On Social Media template by W3Schools</h5>
<p class="btnPost" contenteditable="true">
Status:Feeling Blue
</p>
<button type="button" class="btnPTxt">
<i class="fas fa-pen"></i>
Post
</button>
</div>
O código cria uma divisão, ‘postagens’ configurada como ‘column’, que exibe os
componentes empilhados. Para produzir o efeito que desejamos, com o avatar em linha com o nome e
o ‘time stamp’, criamos duas subdivisões. A primeira com a ‘Figura’ e o ‘Nome’ e a segunda com o
‘Time Stamp’, incorporadas em ‘avt’. Deste modo, o modelo flexível ‘enxerga’ ‘avt’ como um único
elemento a ser colocado na primeira posição da coluna.
O segundo bloco é de texto.
Basta defini-lo como sendo uma divisão que o mesmo ocupará sua posição naturalmente. Definimos a
sua classe como 'comment'.
<div id="postagens"
class="post">
<div id="avt"
class="sameLine">
<div
class="sameLine">
<img
src="../_img/avatar2.png" alt="Avatar" class="me2">
<h3> John
Doe</h3><br>
</div>
<div id=”timeStamp”>
<p>1 minute</p>
</div>
</div>
<div class="comment">
<p>
Lorem
ipsum dolor...
</p>
</div>
</div>
Imagens podem ou não existir e podem ocupar 50% ou 100% da largura do bloco. Para ocupar 50% aplicamos a regra CSS imgHH e para ocupar 100%, aplicamos imgTT. A diferença entre essas duas classes é somente a propriedade 'width'.
.imgHH, .imgTT{
display:flex;
justify-content:flex-start;
flex-direction:column;
margin:0.5em 0.25em 1em 0.25em;
padding:0;
width:50%;
}
.imgTT{
width:100%;
}
Coluna Direita
A coluna da direita contém os mesmos elementos vistos na coluna central, com poucas modificações. O primeiro bloco é um bloco de texto com figura em 100% da largura. Podemos simplesmente copiar o bloco da coluna central na coluna da direita, alterar o texto e a figura e ajustar as margens. A classe ‘comment’ está aplicada à coluna central e a classe ‘rBox’ à coluna da direita:
.comment, .rBox{
display:flex;
flex-direction:column;
border:1px solid lightblue;
box-shadow:2px 2px 1px lightgray;
border-radius:4px;
padding:1em;
margin:0.5em 0 0 0;
}
.rBox{
margin:0
0.5em 0.5em 0.5em;
}
Um último ajuste:manter o cabeçalho fixo durante a rolagem da página. Isso é conseguido especificando-se ‘position’ como ‘fixed’, mantendo ‘top’ em zero. Para evitar que algum elemento se sobreponha ao menu durante a rolagem, especificamos ‘z-index:1’. Do mesmo modo, para evitar que os elementos aparecem por ‘baixo’ do menu, especificamos uma cor de fundo:
#topo{
position:fixed;
top:0;
width:100%;
max-width:88em;
border:1px, solid, black;
background-color:white;
z-index:1;
margin:auto;
}
Social Media
Com esse artigo completamos este tutorial. Acesse o site que desenvolvemos clicando no link: social media with flex-box model.
Download
O código completo pode ser
baixado da seção de downloads, que pode ser acessado por este atalho.
Obrigado a todos
que acompanharam este tutorial!