Continuando os meus estudos semanais, iniciei a semana da independência apenas após o feriado, no dia 08 de setembro (🖕 FORA BOLSONARO 🖕). Por ser uma semana menor, escolhi um desafio um pouco mais simples, desta vez focado em responsividade. O desafio escolhido foi o Sunnyside agency landing page, um projeto bem colorido e divertido de se fazer.
Briefing
Desta vez o projeto não tem nenhuma API para ser consumida, são apenas textos e imagens estáticas renderizadas na tela. O desafio é uma landing page, bem colorida e cheia de imagens. O seu design todo quadradão parece ser perfeito para exercitar conceitos de responsividade.
Assim como todos os desafios do FronEndMentor que fiz até então (tanto os quais eu já escrevi aqui, quanto os quais ainda irei escrever), este também foi desenvolvido para dispositivos mobile de 375px, quanto para telas de desktop de 1440px.
Tools
Aqui fiquei em dúvida sobre qual tecnologia usar, SASS me pareceu uma boa escolha, mas no final acabei indo, por força do hábito, de styled-components 💅 hahah.
O projeto
Inicie o projeto com CRA + typescript. Tenho usado TS em todos os projetos, até nos mais simples. No final das contas, mal não vai fazer espero.
Após aquela limpeza básica nos arquivos, instalei o styled-components, e já fui logo escrevendo. Assim como meus últimos projetos, optei por iniciar pela versão mobile, e meu primeiro componente aqui foi o <Header />
. Ele foi bem simples de fazer, pois é apenas uma logo em svg, e alguns <a>
. Para fazer o Hamburger Menu eu uso um snippet que criei que basicamente é isso aqui:
<input type="checkbox" id="menu_hamburger" />
<label htmlFor="menu_hamburger">
<img src="/icon-hamburger.svg" alt="menu" />
</label>
No CSS eu deixo o <input>
invisível com display: none
e visibility: hidden
. A <label>
aqui vai ser o ícone do menu, e ao mesmo tempo vai servir para marcar ou desmarcar o <input>
. Abaixo desse código entra a <nav>
, que em um primeiro momento também vai estar invisível, usando as mesmas propriedades já mostradas ali em cima. Para torná-la visível, eu uso o seletor checked do input, desta forma:
input:checked ~ nav {}
Então, quando o input não estiver marcado, apenas a logo e o icone do Hamburger Menu, ao ser marcado o menu flutuante aparece. Simples né?! Eu poderia fazer a mesma coisa usando o useState()
do React, mas acho que pesaria mais do que simplesmente usar CSS.
Além do <Header>
, na página inicial temos a imagem de uma laranja gigante, que ocupa a tela toda, como se fosse um background. No entanto, não usei ela como background, mas sim como um <img>
, pois neste ponto notei que quase todas as imagens tinham versões otimizadas(??) para cada tipo de tela. Ao longo do texto vou falar melhor sobre como optei para identificar o tamanho da tela do usuário e usar a imagem mais adequada para cada tipo.
Com a <img>
já em tela, dei a ela position: absolute
e z-index: -1
para jogar ela para de baixo de tudo na tela inicial. Com mais um <h1>
a tela inicial já estava pronta e funcional.
A próxima parte é composta por uma imagem seguida de uma <div>
com um título e texto. Aqui já tinha noção que na versão desktop a ordem de exibição estaria "invertida" em relação a versão mobile, além de ser exibida na horizontal. Para resolver isso coloquei a <div>
seguido da <img>
e usei o código CSS a seguir:
display: flex;
flex-direction: column-reverse;
align-items: center;
justify-content: center;
Assim, quando fosse para versão desktop seria apenas colocar flex-direction: row
e já estaria tudo pronto. Poderia ter feito o inverso também, aplicando reverse-row na versão desktop futuramente. E com isso já tinha matado duas seções. Na verdade quase três, pois o próximo componente, que faria apenas no dia seguinte, teria a mesma estrutura que esse último.
No dia seguinte, 09/09, não tive problemas para fazer o terceiro componente, e nem os demais. Em um componente que chamei de <Gallery />
, deveria ser exibido quatro imagens, duas em cima e duas em baixo, na versão mobile, e as quatro uma ao lado da outra na versão desktop, meu primeiro pensamento foi usar grid, mas achei que seria mais fácil usar flexbox, da seguinte forma:
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
Definindo a largura de cada imagem em 50% em relação a tela, assim quando fosse para a versão desktop seria apenas usar flex-wrap: nowrap
para deixá-las na horizontal. Nesse dia demorei mais tentando descobrir as medidas de padding
e margin
no Photoshop do que outra coisa hahaha. Essas propriedades só são disponibilizadas para quem paga o premium do site, através do Figma ou Sketch.
Ao começar a fazer o <Footer />
percebi que uma das cores apontadas no style-guide do projeto estava bem longe do que deveria ser, então usei o conta gotas do PS para identificar a cor real do projeto. Resolvi falar sobre isso aqui porque vários outros projetos vieram com cores erradas ou cores faltando, esse não foi diferente 🙄 (mas como é de graça né).
O projeto original também disponibilizou logos de redes sociais em .svg, mas optei por usar o react-icons, pois fica mais fácil de trabalhar active states, como hover por exemplo.
Foi no footer onde tive meu primeiro problema, a logo disponibilizada veio em svg e na cor branca, porém no footer deveria dar outra cor para ela. Eu sei que posso usar jQuery para achar a tag img e buscar a propriedade fill dentro do svg, porém fiz da forma mais fácil aqui hihihi 😛 usei o svg inline, e mudei manualmente a cor de preenchimento dele.
Com isso já estava pronto a versão mobile, e mais um dia havia se encerrado.
No último dia de projeto, precisava apenas terminar os ajustes para versão desktop, o que não foi nada difícil (já falei sobre os principais ajustes ao longo do texto). Quero destacar como fiz para escolher qual versão da imagem usar de acordo com cada tamanho de tela.
Todos os meus componentes foram agrupados no App.tsx
, assim, neste documento criei um state para guardar a largura da tela, desta forma const [screenWidth, setScreenWidth] = useState(0)
. Para pegar a largura da tela usei o seguinte código:
window.onresize = () => {
const w = document.body.clientWidth
setWidth(w)
}
Assim, cada vez que a tela é redimencionada, é definido um novo valor para width
, essa variável foi passada como uma prop para cada um dos componentes que contenham imagens. Dentro de cada componente fiz uma verificação ternária dentro do return para exibir a imagem correta, assim ó:
...code
return (
{width <= 700
? <img src="/mobile/image.jpg" alt="blah" />
: <img src="/desktop/image.jpg" alt="blah" />
}
)
***Não use blah no alt das <img>
caga com a acessibilidade da aplicação - aqui é apenas um exemplo.
E assim se encerrou mais um projetinho do FrontEndMentor. Ah! hoje 10/09 realizei minha inscrição para a #nextjsconf da
@vercel, que será realizada mais para o final de outubro.
Github do projeto: https://github.com/GuihLeme/sunnyside-landing-page
Site: https://sunnyside-landing-page-pi.vercel.app/
Top comments (0)