Criando um blog com Jekyll - Parte 3

| #frontend #jekyll #sass #javascript

Introdução

Fala galera, hoje daremos continuidade ao tutorial de como criar um blog com Jekyll. Nessa parte, vamos adicionar o nosso CSS utilizando o SASS, também vamos adicionar JavaScript (incluindo o plugin de pesquisa) e corrigir alguns erros nos arquivos. Deixarei a parte de escrever posts para a parte final junto com a parte de adicionar páginas.

Se você ainda não leu as outras partes, leia e depois volte aqui:

Agora, vamos lá!

Estilizando o blog com SASS

Vamos começar pelo SASS, primeiramente você deve ter ele instalado em sua máquina, se você não tem veja como instalar aqui.

Depois de instalado, vamos começar a estilizar. Abra o arquivo main.scss, que está na pasta css, que se encontra dentro da pasta assets. O arquivo ficou assim:

---
# Only the main Sass file needs front matter (the dashes are enough)
---
@charset "utf-8";

/*-------------------------
---- Fontes importadas ----
-------------------------*/
// Open Sans
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700); 

/*-----------------
---- Variáveis ----
-----------------*/
// Fontes
$fonte-padrao: 'Open Sans', Arial, sans-serif;

// Cores
$azul: #3498db;
$azul-escuro: #1f74bf;
$branco: #fff;
$preto: #3c3c3c;

// Breakpoints
$bp-celular: 600px;
$bp-tablet: 800px;


/*--------------------
---- Placeholders ----
--------------------*/
%margins {
    margin: 1em 0;
}

/*--------------
---- Mixins ----
--------------*/
@mixin media-query($device) {
    @media screen and (max-width: $device) {
        @content;
    }
}

/*--------------------------------
---- Arquivos SASS importados ----
--------------------------------*/
@import
        "base",
        "layout",
        "syntax-highlighting",
        "responsive"
;

Aqui definimos as variáveis que utilizaremos durante a estilização, criamos um placeholder para o tamanho das margens, também criamos um mixin para as nossas media queries. No final fazemos a importação dos arquivos que estão na pasta _sass.

Depois disso, abra a pasta _sass, dentro dela tem 3 arquivos:

  • _base.scss
  • _layout.scss
  • _syntax-highlighting.scss

Iremos adicionar um novo arquivo: _responsive.scss, que será o arquivo responsável pela estilização para dispositivos móveis.

_base.scss

/*-------------
---- Reset ----
-------------*/
*, *:before, *:after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

button {
    padding: 0;
    background: none;
    border: 0;
    overflow: visible;
}

/*------------
---- Body ----
------------*/
body {
    font-family: $fonte-padrao;
    color: $preto; 
}

/*------------------
---- Tipografia ----
------------------*/
h1 {
    font-size: 24pt;
    line-height: 28pt;
}

h2 {
    font-size: 20pt;
    line-height: 24pt;
}

h3 {
    font-size: 16pt;
    line-height: 20pt;
}

h4 {
    font-size: 14pt;
    line-height: 16pt;
}

h5 {
    font-size: 12pt;
    line-height: 14pt;
}

h6 {
    font-size: 10pt;
    line-height: 12pt;
}

p, a, li {
    font-size: 14pt;
    line-height: 18pt;
}

p {
    @extend %margins;
}

h4, h5, h6 {
    text-transform: uppercase;
}

/*-------------
---- Links ----
-------------*/
a {
    color: $azul;

    &:hover {
        color: $azul-escuro;
    }
}

/*--------------
---- Listas ----
--------------*/
ul {
    list-style: disc;
}

ul, ol {
    padding-left: 20px;

    li {
        padding: 5px 0;
    }
}

/*---------------
---- Imagens ----
---------------*/
img {
    max-width: 100%;
    vertical-align: middle;
}

figure > img {
    display: block;
}

.center {
  display: block;
  margin: 0 auto;
}

.right {
  float: right;
}

.left {
  float: left;
}

/*-------------------
---- Blockquotes ----
-------------------*/
blockquote {
    border-left: 4px solid $azul;
    font-size: 16pt;
    letter-spacing: -1px;
    font-style: italic;

    > :last-child {
        margin-bottom: 0;
    }
}

Aqui temos a base do estilo do blog, primeiro fazemos um reset, depois estilizamos a tipografia, links, listas, imagens e o blockquotes.

_layout.scss

/*-----------------------
---- Header | Footer ----
-----------------------*/
.header {
    a {
        text-decoration: none;
    }
}

.footer {
    color: $branco;
    text-shadow: 0px 2px 0px rgba(31, 116, 191, 1);

    a {
        color: $branco;
    }

    p {
        margin: 0;
    }
}

.header, .footer {
    padding: 15px;
    background: $azul;
    text-align: center;
}

/*-------------------
---- Título Site ----
-------------------*/
.title {
    clear: both;
    padding: 20px 0;
    
    a {
        color: $branco;
        text-shadow: 0px 5px 0px rgba(31, 116, 191, 1);
    }

    h1 a {
        font-size: 32pt;
        line-height: 42pt;
        text-transform: uppercase;
    }

    h2 a {
        font-size: 24pt;
        line-height: 34pt;
    }
}

/*------------
---- Menu ----
------------*/
.bt-menu {
    display: none;
    float: left;
}

.menu {
    li {
        float: left;
        margin: 0 15px 0 0;
        list-style: none;

        &:last-child {
            margin-right: none;
        }
    }

    a {
        font-size: 16pt;
        color: $branco;

        &:hover {
            text-decoration: underline;
        }
    }
}

/*----------------
---- Pesquisa ----
----------------*/
.bt-search {
    float: right;
}

#search-container {
    display: none;
    top: 0;
    left: 0;
    padding: 10px;
    position: fixed;
    width: 100%;
    height: 100%;
    z-index: 1;
    background-color: rgba(0, 0, 0, 0.8);

    input[type=text]{
        width: 400px;
        height: 30px;
        margin: 10px auto;
        background: transparent;
        border: 0;
        border-bottom: 1px solid $branco;
        outline: 0;
        text-align: center;
        font-size: 16pt;
        color: $branco;
    }

    ::-webkit-input-placeholder{
        color: $branco;
    }

    :-ms-input-placeholder {
        color: $branco;
    }

    ::-ms-input-placeholder {
        color: $branco;
    }

    ::-moz-placeholder {
        color: $branco;
    }

    a {
        display: block;
        margin: 10px;
        color: $branco;

        &:hover {
            color: $azul;
            text-decoration: underline;
        }
    }
}  

/*------------------
---- Ícones SVG ----
------------------*/
.icon-top {
    width: 25px;
    height: 25px;
    fill: $branco;
    cursor: pointer;
}

.icon {
  width: 40px;
  height: 40px;
  margin: 5px;
  display: inline-block;
  fill: $azul;
}

/*---------------------
---- Página | Post ----
---------------------*/
.home {
    text-align: center;
}

.page-content {
    display: block;
    padding: 35px 30px;
}

.post-content {
    h2, h3, h4, h5, h6 {
        margin: 20px 0;
    }
}

.post-list {
    list-style: none;
}

.page-title,
.post-title {
  border-bottom: 1px solid $preto;
  padding: 5px 0;
}

.post-meta {
  font-size: 10pt;
  line-height: 16pt;
}

.post-link {
  text-decoration: none;
  font-size: 24pt;
  line-height: 28pt;
}

.tags {
  margin-top: 1em;

  a {
    border-right: 1px solid $azul;
    padding: 0 5px;

    &:last-child {
        border-right: none;
    }
  }
}

/*-------------
---- Autor ----
-------------*/
.img-author {
  width: 150px;
  height: 150px;
  float: left;
  margin-right: 20px;
  border-radius: 100%;
  border: 3px solid $azul;
}

.author {
  background: darken($branco, 5%);
  padding: 15px;
  @extend %margins;

  .details {
    @extend %margins;
  }

  .name a {
    font-size: 18pt;
    text-decoration: none;
  }
}

/*------------------------------------------------
---- Botões de Compartilhamento | Comentários ----
------------------------------------------------*/
.share, .comments {
  text-align: center;
  border-top: 1px solid $preto;
  padding: 10px;
}

.share {
  a {
    text-decoration: none;
  }

  .icon {
    margin-top: 10px;
    
    &:hover {
      fill: darken($azul, 15%);
    }
  }
}

Esse é o arquivo responsável pela estrutura do layout. Você pode estilizar do jeito que quiser, fiz conforme o layout que mostrei na primeira parte do tutorial.

_responsive.scss

@include media-query($bp-tablet) {
	/*------------
	---- Menu ----
	------------*/
	.bt-menu {
		display: block;
	}

    .menu {
    	display: none;
    	clear: both;

    	li {
        	float: none;
        	display: block;
        	margin: 0;
        	padding: 10px;
        	border-bottom: 1px solid $branco;

        	&:last-child {
            	border-bottom: none;
        	}
    	}
	}
}

@include media-query($bp-celular) {
	/*-------------------
	---- Título Site ----
	-------------------*/
	.title {
    	h1 a {
        	font-size: 24pt;
        	line-height: 32pt;
        	text-transform: capitalize;
    	}

    	h2 a {
        	font-size: 16pt;
        	line-height: 24pt;
    	}
	}
	
	/*---------------------
	---- Página | Post ----
	---------------------*/
	.page-content {
  		padding: 25px 20px;
	}


	.post-list, .post-container {
  		padding: 0;
	}
	
	/*----------------
	---- Pesquisa ----
	----------------*/
	#search-container {

  		input[type=text]{
    		width: 80%;
  		}
	}

	/*-------------
	---- Autor ----
	-------------*/
	.author {
		text-align: center;

		.email {
			font-size: 12pt;
		}
	}

	.img-author {
		float: none;
		display: block;
		margin: 0 auto;
	}
}

Adaptamos o layout para os dispositivos móveis, incluimos os mixins que criamos no main.scss com os breakpoints que definimos também lá.

_syntax-highlighting.scss

/*--------------
---- Código ----
--------------*/
pre,
code {
    font-size: 15px;
    border: 1px solid $azul;
    border-radius: 3px;
    background: #272822;
}

code {
    padding: 1px 5px;
    color: $branco;
}

pre {
    padding: 8px 12px;
    overflow-x: auto;

    > code {
        border: 0;
        padding-right: 0;
        padding-left: 0;
    }
}

/*----------------------------------
---- Syntax highlighting styles ----
----------------------------------*/
.highlight {
    background: #272822;

    .highlighter-rouge & {
      background: #272822;
    }

    .c { color: #75715e } /* Comment */
    .err { color: #960050; background-color: #1e0010 } /* Error */
    .k { color: #66d9ef } /* Keyword */
    .l { color: #ae81ff } /* Literal */
    .n { color: #f8f8f2 } /* Name */
    .o { color: #f92672 } /* Operator */
    .p { color: #f8f8f2 } /* Punctuation */
    .cm { color: #75715e } /* Comment.Multiline */
    .cp { color: #75715e } /* Comment.Preproc */
    .c1 { color: #75715e } /* Comment.Single */
    .cs { color: #75715e } /* Comment.Special */
    .ge { font-style: italic } /* Generic.Emph */
    .gs { font-weight: bold } /* Generic.Strong */
    .kc { color: #66d9ef } /* Keyword.Constant */
    .kd { color: #66d9ef } /* Keyword.Declaration */
    .kn { color: #f92672 } /* Keyword.Namespace */
    .kp { color: #66d9ef } /* Keyword.Pseudo */
    .kr { color: #66d9ef } /* Keyword.Reserved */
    .kt { color: #66d9ef } /* Keyword.Type */
    .ld { color: #e6db74 } /* Literal.Date */
    .m { color: #ae81ff } /* Literal.Number */
    .s { color: #e6db74 } /* Literal.String */
    .na { color: #a6e22e } /* Name.Attribute */
    .nb { color: #f8f8f2 } /* Name.Builtin */
    .nc { color: #a6e22e } /* Name.Class */
    .no { color: #66d9ef } /* Name.Constant */
    .nd { color: #a6e22e } /* Name.Decorator */
    .ni { color: #f8f8f2 } /* Name.Entity */
    .ne { color: #a6e22e } /* Name.Exception */
    .nf { color: #a6e22e } /* Name.Function */
    .nl { color: #f8f8f2 } /* Name.Label */
    .nn { color: #f8f8f2 } /* Name.Namespace */
    .nx { color: #a6e22e } /* Name.Other */
    .py { color: #f8f8f2 } /* Name.Property */
    .nt { color: #f92672 } /* Name.Tag */
    .nv { color: #f8f8f2 } /* Name.Variable */
    .ow { color: #f92672 } /* Operator.Word */
    .w { color: #f8f8f2 } /* Text.Whitespace */
    .mf { color: #ae81ff } /* Literal.Number.Float */
    .mh { color: #ae81ff } /* Literal.Number.Hex */
    .mi { color: #ae81ff } /* Literal.Number.Integer */
    .mo { color: #ae81ff } /* Literal.Number.Oct */
    .sb { color: #e6db74 } /* Literal.String.Backtick */
    .sc { color: #e6db74 } /* Literal.String.Char */
    .sd { color: #e6db74 } /* Literal.String.Doc */
    .s2 { color: #e6db74 } /* Literal.String.Double */
    .se { color: #ae81ff } /* Literal.String.Escape */
    .sh { color: #e6db74 } /* Literal.String.Heredoc */
    .si { color: #e6db74 } /* Literal.String.Interpol */
    .sx { color: #e6db74 } /* Literal.String.Other */
    .sr { color: #e6db74 } /* Literal.String.Regex */
    .s1 { color: #e6db74 } /* Literal.String.Single */
    .ss { color: #e6db74 } /* Literal.String.Symbol */
    .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
    .vc { color: #f8f8f2 } /* Name.Variable.Class */
    .vg { color: #f8f8f2 } /* Name.Variable.Global */
    .vi { color: #f8f8f2 } /* Name.Variable.Instance */
    .il { color: #ae81ff } /* Literal.Number.Integer.Long */

    .gh { } /* Generic Heading & Diff Header */
    .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
    .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
    .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */
}

Por fim, estilizamos os highlights do blog, utilizei o mesmo que uso nesse meu blog. E terminamos a estilização, vamos agora adicionar JavaScript.

Adicionando JavaScript

Primeira coisa que iremos fazer é instalar o Bower para gerenciar as dependências do blog. Para instalar ele, você deve já ter instalado em sua máquina o Node.js, npm e Git. Com eles já instalados, digite no terminal:

npm install -g bower

Para verificar se ele foi instalado com sucesso, digite:

bower -v
# 1.6.8

Antes de instalar as dependências que iremos utilizar no blog, precisamos listá-las. Para isso digite o comando bower init. Ele irá nos fazer algumas perguntas, responda com as informações do seu blog (nem todas as perguntas precisam ser respondidas). Feito isso o bower irá criar o arquivo bower.json, você pode editá-lo como quiser.

Agora vamos instalar 2 dependências: o jQuery e o Simple Jekyll Search. Para instalar e já listá-las no arquivo bower.json, digite o comando:

# Instalar o Simple Jekyll Search
bower install --save simple-jekyll-search

# Instalar o jQuery
bower install --save jquery

Vamos mudar o diretório das nossas dependências, ele ficará no seguinte caminho: /assets/components/. Para isso crie um arquivo chamado .bowerrc e nele adicione:

{
    "directory" : "assets/components"
}

Feito isso, exclua a pasta bower_components.

No final, depois de editado, o meu arquivo bower.json ficou assim:

{
  "name": "Tutorial Jekyll",
  "homepage": "https://github.com/mateussmedeiros/tutorial-jekyll",
  "authors": [
    "Mateus Medeiros <mateusdesousamedeiros@hotmail.com>"
  ],
  "description": "Tutorial de como construir um blog com Jekyll",
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "simple-jekyll-search": "latest",
    "jquery": "latest"
  }
}

Pronto, instalamos o jQuery e o Simple Jekyll Search. Agora vamos implementá-los.

Implementando a Pesquisa

Primeiramente, crie o arquivo search.json, e digite isso:

---
---
[
  
  {% for post in site.posts %}
    {
      "title"    : "{{ post.title | escape }}",
      "category" : "{{ post.category }}",
      "tags"     : "{{ post.tags | join: ', ' }}",
      "url"      : "{{ site.baseurl }}{{ post.url }}",
      "date"     : "{{ post.date }}"
    } {% unless forloop.last %},{% endunless %}
  {% endfor %}
  
]

Depois dentro da pasta assets/js, crie um arquivo script.js e digite:

// Abrir e Fechar - Barra de Pesquisa
$(".bt-search").click(function() {
	$("#search-container").show();

	if ( $("#search-container").is(":visible") ) {
		$(".bt-search").attr('aria-expanded', 'true');
	}
});

$(".bt-close").click(function() {
	$("#search-container").hide();

	if ( $("#search-container").is(":hidden") ) {
		$(".bt-search").attr('aria-expanded', 'false');
	}
});

// Simple Jekyll Search
SimpleJekyllSearch({
  searchInput: document.getElementById('search-input'),
  resultsContainer: document.getElementById('results-container'),
  json: '/search.json',
  searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
  noResultsText: 'Sem resultados'
})

Primeiro criamos a função que abre e fecha a barra de pesquisa e depois implementamos o plugin Simple Jekyll Search.

Abrindo e fechando o Menu

Ainda no arquivo script.js, adicione isso:

// Abrir e Fechar - Menu
$(".bt-menu").click(function() {
	$(".menu").toggle();

	if ( $(".menu").is(":visible") ) {
		$(".bt-menu").attr('aria-expanded', 'true');

	} else {
		$(".bt-menu").attr('aria-expanded', 'false');
	};
});

// Retirar o estilo com o redimensionamento da tela
$(window).resize(function(){
	if(window.innerWidth > 800) {
		$(".menu").removeAttr("style");
		$("#search-container").removeAttr("style");
	}
});

Primeiro criamos a função que abre e fecha o menu e depois corrigimos um bug que é gerado quando redimensionamos a tela.

Chamando os arquivos js

Já configuramos o nosso JavaScript, agora vamos chamar os arquivos. Para isso abra o arquivo footer.html e adicione as seguintes linhas:

<script src="/assets/components/jquery/dist/jquery.min.js"></script>
<script src="/assets/components/simple-jekyll-search/dest/jekyll-search.js"></script>
<script src="/assets/js/script.js"></script>

Pronto, agora nosso JavaScript já está funcionando corretamente!

Corrigindo erros no arquivos

Se você acessar o blog, vai perceber que os ícones SVG não estão aparecendo. Isso acontece porque não chamamos o arquivo svg.html no nosso head.html, para corrigir isso adicione {% include svg.html %} no arquivo head.html e pronto, está corrigido!

Conclusão

Adicionamos CSS e JavaScript ao blog, agora ele já está praticamente pronto. Na próxima e última parte desse tutorial, irei ensinar como escrever posts e adicionar páginas ao blog, também iremos subir ele para o GitHub. Aguarde!

Dúvidas? Comente!


Mateus Medeiros - Desenvolvedor Front End

Autor

Mateus Medeiros

Desenvolvedor Front End apaixonado por novas tecnologias.

Comentários