portifólio
|

Como criar portfólio online com HTML/CSS + Bootstrap 5

Neste tutorial você aprenderá como criar seu portfólio online do zero utilizando HTML5, CSS3, JavaScript e Bootstrap 5.

O Bootstrap é um framework CSS amplamente adotado que oferece um sistema de grid responsivo, componentes pré-estilizados (navbar, botões, carousel) e utilitários de espaçamento, cores e tipografia, permitindo acelerar o desenvolvimento e garantir consistência visual em diferentes dispositivos.

Com ele, você terá à disposição blocos de código prontos para navbar colapsável, carrossel de imagens e estilos de rodapé, reduzindo a necessidade de escrever CSS do zero e focando na personalização do seu design.

Passo 1 — Estrutura de arquivos

Crie uma pasta para o projeto (portifolio) e, dentro dela, organize:

				
					portifolio/
├── index.html
├── style.css

				
			

Passo 2 — Criar template básico HTML e CSS

  • Abra o index.html.

  • Insira a declaração do tipo de documento e as tags principais:

				
					<!DOCTYPE html>
<html lang="pt-br">
<head>
  
</head>
<body>
   <script data-no-optimize="1">window.lazyLoadOptions=Object.assign({},{threshold:300},window.lazyLoadOptions||{});!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LazyLoad=e()}(this,function(){"use strict";function e(){return(e=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,a=arguments[e];for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])}return t}).apply(this,arguments)}function o(t){return e({},at,t)}function l(t,e){return t.getAttribute(gt+e)}function c(t){return l(t,vt)}function s(t,e){return function(t,e,n){e=gt+e;null!==n?t.setAttribute(e,n):t.removeAttribute(e)}(t,vt,e)}function i(t){return s(t,null),0}function r(t){return null===c(t)}function u(t){return c(t)===_t}function d(t,e,n,a){t&&(void 0===a?void 0===n?t(e):t(e,n):t(e,n,a))}function f(t,e){et?t.classList.add(e):t.className+=(t.className?" ":"")+e}function _(t,e){et?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")}function g(t){return t.llTempImage}function v(t,e){!e||(e=e._observer)&&e.unobserve(t)}function b(t,e){t&&(t.loadingCount+=e)}function p(t,e){t&&(t.toLoadCount=e)}function n(t){for(var e,n=[],a=0;e=t.children[a];a+=1)"SOURCE"===e.tagName&&n.push(e);return n}function h(t,e){(t=t.parentNode)&&"PICTURE"===t.tagName&&n(t).forEach(e)}function a(t,e){n(t).forEach(e)}function m(t){return!!t[lt]}function E(t){return t[lt]}function I(t){return delete t[lt]}function y(e,t){var n;m(e)||(n={},t.forEach(function(t){n[t]=e.getAttribute(t)}),e[lt]=n)}function L(a,t){var o;m(a)&&(o=E(a),t.forEach(function(t){var e,n;e=a,(t=o[n=t])?e.setAttribute(n,t):e.removeAttribute(n)}))}function k(t,e,n){f(t,e.class_loading),s(t,st),n&&(b(n,1),d(e.callback_loading,t,n))}function A(t,e,n){n&&t.setAttribute(e,n)}function O(t,e){A(t,rt,l(t,e.data_sizes)),A(t,it,l(t,e.data_srcset)),A(t,ot,l(t,e.data_src))}function w(t,e,n){var a=l(t,e.data_bg_multi),o=l(t,e.data_bg_multi_hidpi);(a=nt&&o?o:a)&&(t.style.backgroundImage=a,n=n,f(t=t,(e=e).class_applied),s(t,dt),n&&(e.unobserve_completed&&v(t,e),d(e.callback_applied,t,n)))}function x(t,e){!e||0<e.loadingCount||0<e.toLoadCount||d(t.callback_finish,e)}function M(t,e,n){t.addEventListener(e,n),t.llEvLisnrs[e]=n}function N(t){return!!t.llEvLisnrs}function z(t){if(N(t)){var e,n,a=t.llEvLisnrs;for(e in a){var o=a[e];n=e,o=o,t.removeEventListener(n,o)}delete t.llEvLisnrs}}function C(t,e,n){var a;delete t.llTempImage,b(n,-1),(a=n)&&--a.toLoadCount,_(t,e.class_loading),e.unobserve_completed&&v(t,n)}function R(i,r,c){var l=g(i)||i;N(l)||function(t,e,n){N(t)||(t.llEvLisnrs={});var a="VIDEO"===t.tagName?"loadeddata":"load";M(t,a,e),M(t,"error",n)}(l,function(t){var e,n,a,o;n=r,a=c,o=u(e=i),C(e,n,a),f(e,n.class_loaded),s(e,ut),d(n.callback_loaded,e,a),o||x(n,a),z(l)},function(t){var e,n,a,o;n=r,a=c,o=u(e=i),C(e,n,a),f(e,n.class_error),s(e,ft),d(n.callback_error,e,a),o||x(n,a),z(l)})}function T(t,e,n){var a,o,i,r,c;t.llTempImage=document.createElement("IMG"),R(t,e,n),m(c=t)||(c[lt]={backgroundImage:c.style.backgroundImage}),i=n,r=l(a=t,(o=e).data_bg),c=l(a,o.data_bg_hidpi),(r=nt&&c?c:r)&&(a.style.backgroundImage='url("'.concat(r,'")'),g(a).setAttribute(ot,r),k(a,o,i)),w(t,e,n)}function G(t,e,n){var a;R(t,e,n),a=e,e=n,(t=Et[(n=t).tagName])&&(t(n,a),k(n,a,e))}function D(t,e,n){var a;a=t,(-1<It.indexOf(a.tagName)?G:T)(t,e,n)}function S(t,e,n){var a;t.setAttribute("loading","lazy"),R(t,e,n),a=e,(e=Et[(n=t).tagName])&&e(n,a),s(t,_t)}function V(t){t.removeAttribute(ot),t.removeAttribute(it),t.removeAttribute(rt)}function j(t){h(t,function(t){L(t,mt)}),L(t,mt)}function F(t){var e;(e=yt[t.tagName])?e(t):m(e=t)&&(t=E(e),e.style.backgroundImage=t.backgroundImage)}function P(t,e){var n;F(t),n=e,r(e=t)||u(e)||(_(e,n.class_entered),_(e,n.class_exited),_(e,n.class_applied),_(e,n.class_loading),_(e,n.class_loaded),_(e,n.class_error)),i(t),I(t)}function U(t,e,n,a){var o;n.cancel_on_exit&&(c(t)!==st||"IMG"===t.tagName&&(z(t),h(o=t,function(t){V(t)}),V(o),j(t),_(t,n.class_loading),b(a,-1),i(t),d(n.callback_cancel,t,e,a)))}function $(t,e,n,a){var o,i,r=(i=t,0<=bt.indexOf(c(i)));s(t,"entered"),f(t,n.class_entered),_(t,n.class_exited),o=t,i=a,n.unobserve_entered&&v(o,i),d(n.callback_enter,t,e,a),r||D(t,n,a)}function q(t){return t.use_native&&"loading"in HTMLImageElement.prototype}function H(t,o,i){t.forEach(function(t){return(a=t).isIntersecting||0<a.intersectionRatio?$(t.target,t,o,i):(e=t.target,n=t,a=o,t=i,void(r(e)||(f(e,a.class_exited),U(e,n,a,t),d(a.callback_exit,e,n,t))));var e,n,a})}function B(e,n){var t;tt&&!q(e)&&(n._observer=new IntersectionObserver(function(t){H(t,e,n)},{root:(t=e).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}))}function J(t){return Array.prototype.slice.call(t)}function K(t){return t.container.querySelectorAll(t.elements_selector)}function Q(t){return c(t)===ft}function W(t,e){return e=t||K(e),J(e).filter(r)}function X(e,t){var n;(n=K(e),J(n).filter(Q)).forEach(function(t){_(t,e.class_error),i(t)}),t.update()}function t(t,e){var n,a,t=o(t);this._settings=t,this.loadingCount=0,B(t,this),n=t,a=this,Y&&window.addEventListener("online",function(){X(n,a)}),this.update(e)}var Y="undefined"!=typeof window,Z=Y&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),tt=Y&&"IntersectionObserver"in window,et=Y&&"classList"in document.createElement("p"),nt=Y&&1<window.devicePixelRatio,at={elements_selector:".lazy",container:Z||Y?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_poster:"poster",class_applied:"applied",class_loading:"litespeed-loading",class_loaded:"litespeed-loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1},ot="src",it="srcset",rt="sizes",ct="poster",lt="llOriginalAttrs",st="loading",ut="loaded",dt="applied",ft="error",_t="native",gt="data-",vt="ll-status",bt=[st,ut,dt,ft],pt=[ot],ht=[ot,ct],mt=[ot,it,rt],Et={IMG:function(t,e){h(t,function(t){y(t,mt),O(t,e)}),y(t,mt),O(t,e)},IFRAME:function(t,e){y(t,pt),A(t,ot,l(t,e.data_src))},VIDEO:function(t,e){a(t,function(t){y(t,pt),A(t,ot,l(t,e.data_src))}),y(t,ht),A(t,ct,l(t,e.data_poster)),A(t,ot,l(t,e.data_src)),t.load()}},It=["IMG","IFRAME","VIDEO"],yt={IMG:j,IFRAME:function(t){L(t,pt)},VIDEO:function(t){a(t,function(t){L(t,pt)}),L(t,ht),t.load()}},Lt=["IMG","IFRAME","VIDEO"];return t.prototype={update:function(t){var e,n,a,o=this._settings,i=W(t,o);{if(p(this,i.length),!Z&&tt)return q(o)?(e=o,n=this,i.forEach(function(t){-1!==Lt.indexOf(t.tagName)&&S(t,e,n)}),void p(n,0)):(t=this._observer,o=i,t.disconnect(),a=t,void o.forEach(function(t){a.observe(t)}));this.loadAll(i)}},destroy:function(){this._observer&&this._observer.disconnect(),K(this._settings).forEach(function(t){I(t)}),delete this._observer,delete this._settings,delete this.loadingCount,delete this.toLoadCount},loadAll:function(t){var e=this,n=this._settings;W(t,n).forEach(function(t){v(t,e),D(t,n,e)})},restoreAll:function(){var e=this._settings;K(e).forEach(function(t){P(t,e)})}},t.load=function(t,e){e=o(e);D(t,e)},t.resetStatus=function(t){i(t)},t}),function(t,e){"use strict";function n(){e.body.classList.add("litespeed_lazyloaded")}function a(){console.log("[LiteSpeed] Start Lazy Load"),o=new LazyLoad(Object.assign({},t.lazyLoadOptions||{},{elements_selector:"[data-lazyloaded]",callback_finish:n})),i=function(){o.update()},t.MutationObserver&&new MutationObserver(i).observe(e.documentElement,{childList:!0,subtree:!0,attributes:!0})}var o,i;t.addEventListener?t.addEventListener("load",a,!1):t.attachEvent("onload",a)}(window,document);</script><script data-no-optimize="1">window.litespeed_ui_events=window.litespeed_ui_events||["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}</script><script data-no-optimize="1">var litespeed_vary=document.cookie.replace(/(?:(?:^|.*;\s*)_lscache_vary\s*\=\s*([^;]*).*$)|^.*$/,"");litespeed_vary||fetch("/wp-content/plugins/litespeed-cache/guest.vary.php",{method:"POST",cache:"no-cache",redirect:"follow"}).then(e=>e.json()).then(e=>{console.log(e),e.hasOwnProperty("reload")&&"yes"==e.reload&&(sessionStorage.setItem("litespeed_docref",document.referrer),window.location.reload(!0))});</script><script data-optimized="1" type="litespeed/javascript" data-src="https://galaxialgorithm.com/wp-content/litespeed/js/235f9809f93f68d68ce04c8dbbcd7fb3.js?ver=59316"></script></body>
</html>

				
			
  • Abra o style.css.

  • Insira o seletor universal (*) para aplicar as regras a todos os elementos da página, e evitar inconsistências de margens e paddings entre navegadores.

				
					/* style.css */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Segoe UI', sans-serif;
  color: #fff;
  background: linear-gradient(135deg, #1a1a2e, #16213e);
  min-height: 100vh;
  background-attachment: fixed;
  background-size: cover;
  line-height: 1.6;
  padding: 0 20px;
}

				
			

Propriedades do *

  • margin: 0; → zera todas as margens externas dos elementos.

  • padding: 0; → zera todo o espaçamento interno dos elementos.

  • box-sizing: border-box; → faz com que o width/height inclua padding e bordas no cálculo.

Propriedades do body

  • font-family: 'Segoe UI', sans-serif; → define “Segoe UI” como fonte principal e “sans‑serif” como opção secundária.

  • color: #fff; → ajusta a cor do texto para branco.

  • background: linear-gradient(135deg, #1a1a2e, #16213e); → aplica um gradiente linear de 135° entre dois tons de azul‑escuro.

  • min-height: 100vh; → garante que o <body> tenha, no mínimo, 100% da altura da janela de visualização.

  • background-attachment: fixed; → fixa o fundo de forma que ele não se mova ao rolar a página.

  • background-size: cover; → faz com que o fundo cubra toda a área disponível, mantendo proporção.

  • line-height: 1.6; → define espaçamento entre linhas igual a 1,6 vezes o tamanho da fonte.

  • padding: 0 20px; → adiciona 20px de espaçamento interno nas laterais esquerda e direita.

Passo 3 — Configurar o head

				
					<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Galaxia – Portfólio</title>
<link rel="icon" href="logo.png" type="image/jpg"/>
<link
  href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css"
  rel="stylesheet"/>
<link data-asynced="1" as="style" onload="this.onload=null;this.rel='stylesheet'"  rel="preload" href="style.css"/>

				
			
  • <meta charset="UTF-8"/> → define a codificação de caracteres para UTF-8.

  • <meta name="viewport" content="width=device-width, initial-scale=1.0"/> → ajusta o layout para ser responsivo em diferentes larguras de tela.

  • <title> → título exibido na aba do navegador e nos resultados de busca.

  • <link rel="icon" href="logo.png" type="image/jpg"/> → adiciona o favicon (ícone do site) que aparece na aba do navegador.

  • <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet"/> → importa o CSS do Bootstrap via CDN, disponibilizando o sistema de grid, componentes (navbar, carousel) e utilitários prontos para uso.

  • <link rel="stylesheet" href="style.css"/> → vincula seu arquivo de estilos personalizados para customizar cores, espaçamentos e efeitos específicos.

Passo 4 — Montar o navbar

Dentro de <body>, crie:

				
					<nav class="navbar navbar-expand-lg">
  <div class="container">
    <a class="navbar-brand d-flex align-items-center" href="index.html">
      <img data-lazyloaded="1" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMCIgaGVpZ2h0PSIzMCIgdmlld0JveD0iMCAwIDMwIDMwIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBzdHlsZT0iZmlsbDojY2ZkNGRiO2ZpbGwtb3BhY2l0eTogMC4xOyIvPjwvc3ZnPg==" decoding="async" data-src="logo.png" alt="Logo" width="30" height="30" class="me-2"/>
      Galaxia
    </a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
            data-bs-target="#navbarNav">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav ms-auto">
        <li class="nav-item"><a class="nav-link active" href="index.html">Início</a></li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" role="button"
             data-bs-toggle="dropdown">Categorias</a>
          <ul class="dropdown-menu">
            <li><a class="dropdown-item" href="aventura.html">Aventura</a></li>
            <li><a class="dropdown-item" href="puzzle.html">Puzzle</a></li>
          </ul>
        </li>
        <li class="nav-item"><a class="nav-link" href="contato.html">Contato</a></li>
      </ul>
    </div>
  </div>
</nav>

				
			

E no arquivo do style.css:

				
					.navbar {
  background-color: #000;
}
.navbar .nav-link {
  color: #fff !important;
}
.navbar .nav-link:hover {
  color: #611968 !important;
}
.navbar-brand {
  color: #fff !important;
  font-weight: bold;
}

				
			
  • background-color → define cor de fundo.

  • color → define cor do texto/link.

  • font-weight → define peso da fonte.

  • !important faz com que esta declaração tenha prioridade sobre outras regras CSS conflitantes para a mesma propriedade.

Passo 5 — Montar o header

Logo após o <nav>, insira:

				
					<header>
  <h1>Portfólio</h1>
</header>

				
			

E no arquivo do style.css:

				
					header {
  text-align: center;                  /* centraliza conteúdo */
  padding: 60px 20px 30px;             /* espaçamento interno */
  background: rgba(147, 47, 167, 0.4); /* fundo roxo semitransparente */
  border-bottom: 2px solid #fff;       /* borda inferior branca */

}
header h1 {
  margin: 0;                           /* remove margem padrão */
  font-size: 2.5rem;                   /* tamanho da fonte */
  color: white;                        /* texto em branco */
}

				
			

Propriedades do header

  • text-align: center; → centraliza horizontalmente o conteúdo interno.

  • padding: 60px 20px 30px; → insere 60px acima, 20px nas laterais e 30px abaixo do conteúdo.

  • background: rgba(147, 47, 167, 0.4); → aplica fundo com 40% de opacidade.

  • border-bottom: 2px solid #00f2ff; → cria uma linha sólida de 2px ciana na base.

Propriedades do header h1

  • margin: 0; → remove margem padrão;
  • font-size → define tamanho de fonte.
      •  

Passo 6 — Construir o main com carrossel

Logo após o <header>, insira:

				
					<main class="container my-5">
  <div id="carouselExampleCaptions" class="carousel slide">
    <div class="carousel-indicators">
      <button type="button" data-bs-target="#carouselExampleCaptions"
              data-bs-slide-to="0" class="active" aria-label="Slide 1"></button>
      <button type="button" data-bs-target="#carouselExampleCaptions"
              data-bs-slide-to="1" aria-label="Slide 2"></button>
      <button type="button" data-bs-target="#carouselExampleCaptions"
              data-bs-slide-to="2" aria-label="Slide 3"></button>
    </div>
    <div class="carousel-inner">
      <div class="carousel-item active">
        <img data-lazyloaded="1" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" decoding="async" data-src="URL_SLIDE_1" class="d-block w-100" alt="Slide 1"/>
        <div class="carousel-caption">
          <h5>Projeto 1</h5>
          <p>Descrição curta do projeto.</p>
          <a href="#" class="btn btn-secondary mt-2">Ver mais</a>
        </div>
      </div>
      
    </div>
    <button class="carousel-control-prev" type="button"
            data-bs-target="#carouselExampleCaptions"
            data-bs-slide="prev">
      <span class="carousel-control-prev-icon"></span>
      <span class="visually-hidden">Anterior</span>
    </button>
    <button class="carousel-control-next" type="button"
            data-bs-target="#carouselExampleCaptions"
            data-bs-slide="next">
      <span class="carousel-control-next-icon"></span>
      <span class="visually-hidden">Próximo</span>
    </button>
  </div>
</main>

				
			

E no arquivo do style.css:

				
					.carousel-item {
  position: relative;
  height: 700px;
  overflow: hidden;
}
.carousel-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.6);
}
.carousel-caption {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: rgba(0, 0, 0, 0.4);
  padding: 20px 30px;
  border-radius: 10px;
  text-align: center;
}
.carousel-caption h5 {
  font-size: 2rem;
  font-weight: bold;
}
.carousel-caption p {
  font-size: 1.1rem;
  margin-bottom: 15px;
}
.carousel-control-prev-icon,
.carousel-control-next-icon {
  background-color: rgba(0, 0, 0);
  border-radius: 50%;
  padding: 15px;
  background-size: 60% 60%;
  width: 50px;
  height: 50px;
}
@media (max-width: 768px) {
  .carousel-item {
    height: 450px;
  }
  .carousel-caption {
    top: 30% !important;
    padding: 10px 15px;
    width: 95%;
  }
  .carousel-caption h5 {
    font-size: 1.4rem;
  }
  .carousel-caption p {
    font-size: 1rem;
    margin-bottom: 10px;
  }
  .carousel-caption .btn {
    font-size: 0.9rem;
    padding: 6px 14px;
  }
}

				
			

Propriedades do carrossel

  • .carousel-item { position: relative; } → define o contêiner como referência para posicionamento absoluto.

  • .carousel-item { height: 700px; } → fixa a altura padrão do slide.

  • .carousel-item { overflow: hidden; } → oculta partes da imagem que ultrapassam o contêiner.

  • .carousel-item img { width: 100%; } → faz a imagem ocupar toda a largura do slide.

  • .carousel-item img { height: 100%; } → faz a imagem ocupar toda a altura do slide.

  • .carousel-item img { object-fit: cover; } → mantém a proporção da imagem recortando o excedente.

  • .carousel-item img { filter: brightness(0.6); } → escurece a imagem em 40% para melhorar contraste.

  • .carousel-caption { position: absolute; } → retira a legenda do fluxo normal para sobrepor a imagem.

  • .carousel-caption { top: 50%; left: 50%; } → posiciona o ponto central da legenda no meio do slide.

  • .carousel-caption { transform: translate(-50%, -50%); } → centraliza perfeitamente a legenda no slide.

  • .carousel-caption { background-color: rgba(0, 0, 0, 0.4); } → adiciona fundo semitransparente atrás da legenda.

  • .carousel-caption { padding: 20px 30px; } → aplica espaço interno na legenda.

  • .carousel-caption { border-radius: 10px; } → arredonda os cantos da caixa da legenda.

  • .carousel-caption { text-align: center; } → centraliza o texto dentro da legenda.

  • .carousel-caption h5 { font-size: 2rem; } → define tamanho do título da legenda.

  • .carousel-caption h5 { font-weight: bold; } → destaca o título em negrito.

  • .carousel-caption p { font-size: 1.1rem; } → define tamanho do parágrafo da legenda.

  • .carousel-caption p { margin-bottom: 15px; } → adiciona espaço abaixo do parágrafo.

  • .carousel-control-prev-icon, .carousel-control-next-icon { background-color: rgba(0,0,0); } → aplica fundo translúcido aos botões de navegação.

  • .carousel-control-prev-icon, .carousel-control-next-icon { border-radius: 50%; } → molda os botões como círculos.

  • .carousel-control-prev-icon, .carousel-control-next-icon { padding: 15px; } → cria espaço interno ao redor do ícone.

  • .carousel-control-prev-icon, .carousel-control-next-icon { background-size: 60% 60%; } → ajusta o tamanho do ícone dentro do círculo.

  • .carousel-control-prev-icon, .carousel-control-next-icon { width: 50px; height: 50px; } → define dimensões fixas para os botões.

Propriedades do carrossel para versão celular

  • @media (max-width: 768px) { .carousel-item { height: 450px; } } → reduz a altura do slide em telas pequenas.

  • @media (max-width: 768px) { .carousel-caption { top: 30% !important; } } → ajusta verticalmente a legenda em mobile.

  • @media (max-width: 768px) { .carousel-caption { padding: 10px 15px; } } → reduz padding da legenda em mobile.

  • @media (max-width: 768px) { .carousel-caption { width: 95%; } } → expande a legenda para quase toda a largura.

  • @media (max-width: 768px) { .carousel-caption h5 { font-size: 1.4rem; } } → diminui o título da legenda no mobile.

  • @media (max-width: 768px) { .carousel-caption p { font-size: 1rem; } } → diminui o texto da legenda no mobile.

  • @media (max-width: 768px) { .carousel-caption p { margin-bottom: 10px; } } → reduz o espaço abaixo do parágrafo em mobile.

  • @media (max-width: 768px) { .carousel-caption .btn { font-size: 0.9rem; } } → ajusta o tamanho do botão da legenda em mobile.

  • @media (max-width: 768px) { .carousel-caption .btn { padding: 6px 14px; } } → ajusta o padding do botão em mobile.

  • !important faz com que esta declaração tenha prioridade sobre outras regras CSS conflitantes para a mesma propriedade.

Nota: dentro da tag 'main', crie o seu carrossel com todos seus jogos desenvolvidos.

Passo 7 — Adicionar o footer

Adicione ao final do <main> a marcação do rodapé e o carregamento do seu script:

				
					 <footer class="bg-dark text-white text-center py-3 mt-auto">
    © 2025 Galaxia. Todos os direitos reservados.
  </footer>
				
			

Passo 8 — Adicionar o JavaScript do Bootstrap

Logo após o <footer>, insira:

				
					<script
  src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.bundle.min.js"
  defer></script> 
				
			
  • <script …> → elemento que carrega e executa código JavaScript.

  • src="https://…/bootstrap.bundle.min.js" → aponta para o bundle oficial do Bootstrap (inclui Popper e plugins necessários).

  • defer → faz com que o navegador baixe o script em paralelo, mas só o execute após o HTML ser totalmente processado, evitando bloqueio de renderização.

Conclusão

Você aprendeu como criar seu portfólio online do zero com HTML, CSS, JavaScript e Bootstrap, incluindo navbar, header, seção de destaque, carousel e footer responsivos.

Posts Similares

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *