I want to align the h1 element with class wish
to the center of its section, both Horizontally and vertically. But am not able to do it for some reason. Please help me out.
Below is the HTML, CSS and JS code.
Note: Since the code was too long it is only the concerned part of the HTML code. I’ll put the complete code if you require it.
The Complete CSS Code is given because I thought it might be necessary for you to understand things better.
/* =================== WISH ================*/
// helper functions
const PI2 = Math.PI * 2
const random = (min, max) => Math.random() * (max - min + 1) + min | 0
const timestamp = _ => new Date().getTime()
// container
class Birthday {
constructor() {
this.resize()
// create a lovely place to store the firework
this.fireworks = []
this.counter = 0
}
resize() {
this.width = canvas.width = window.innerWidth
let center = this.width / 2 | 0
this.spawnA = center - center / 4 | 0
this.spawnB = center + center / 4 | 0
this.height = canvas.height = window.innerHeight
this.spawnC = this.height * .1
this.spawnD = this.height * .5
}
onClick(evt) {
let x = evt.clientX || evt.touches && evt.touches[0].pageX
let y = evt.clientY || evt.touches && evt.touches[0].pageY
let count = random(3, 5)
for (let i = 0; i < count; i++) this.fireworks.push(new Firework(
random(this.spawnA, this.spawnB),
this.height,
x,
y,
random(0, 260),
random(30, 110)))
this.counter = -1
}
update(delta) {
ctx.globalCompositeOperation = 'hard-light'
ctx.fillStyle = `rgba(20,20,20,${ 7 * delta })`
ctx.fillRect(0, 0, this.width, this.height)
ctx.globalCompositeOperation = 'lighter'
for (let firework of this.fireworks) firework.update(delta)
// if enough time passed... create new new firework
this.counter += delta * 3 // each second
if (this.counter >= 1) {
this.fireworks.push(new Firework(
random(this.spawnA, this.spawnB),
this.height,
random(0, this.width),
random(this.spawnC, this.spawnD),
random(0, 360),
random(30, 110)))
this.counter = 0
}
// remove the dead fireworks
if (this.fireworks.length > 1000) this.fireworks = this.fireworks.filter(firework => !firework.dead)
}
}
class Firework {
constructor(x, y, targetX, targetY, shade, offsprings) {
this.dead = false
this.offsprings = offsprings
this.x = x
this.y = y
this.targetX = targetX
this.targetY = targetY
this.shade = shade
this.history = []
}
update(delta) {
if (this.dead) return
let xDiff = this.targetX - this.x
let yDiff = this.targetY - this.y
if (Math.abs(xDiff) > 3 || Math.abs(yDiff) > 3) { // is still moving
this.x += xDiff * 2 * delta
this.y += yDiff * 2 * delta
this.history.push({
x: this.x,
y: this.y
})
if (this.history.length > 20) this.history.shift()
} else {
if (this.offsprings && !this.madeChilds) {
let babies = this.offsprings / 2
for (let i = 0; i < babies; i++) {
let targetX = this.x + this.offsprings * Math.cos(PI2 * i / babies) | 0
let targetY = this.y + this.offsprings * Math.sin(PI2 * i / babies) | 0
birthday.fireworks.push(new Firework(this.x, this.y, targetX, targetY, this.shade, 0))
}
}
this.madeChilds = true
this.history.shift()
}
if (this.history.length === 0) this.dead = true
else if (this.offsprings) {
for (let i = 0; this.history.length > i; i++) {
let point = this.history[i]
ctx.beginPath()
ctx.fillStyle = 'hsl(' + this.shade + ',100%,' + i + '%)'
ctx.arc(point.x, point.y, 1, 0, PI2, false)
ctx.fill()
}
} else {
ctx.beginPath()
ctx.fillStyle = 'hsl(' + this.shade + ',100%,50%)'
ctx.arc(this.x, this.y, 1, 0, PI2, false)
ctx.fill()
}
}
}
let canvas = document.getElementById('birthday')
let ctx = canvas.getContext('2d')
let then = timestamp()
let birthday = new Birthday
window.onresize = () => birthday.resize()
document.onclick = evt => birthday.onClick(evt)
document.ontouchstart = evt => birthday.onClick(evt)
;
(function loop() {
requestAnimationFrame(loop)
let now = timestamp()
let delta = now - then
then = now
birthday.update(delta / 1000)
})()
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap");
/*===== VARIABLES CSS =====*/
:root {
--header-height: 3rem;
--font-semi: 600;
/*===== Colors =====*/
/*Purple 260 - Red 355 - Blue 224 - Pink 340*/
/* HSL color mode */
--hue-color: 224;
--first-color: hsl(var(--hue-color), 89%, 60%);
--first-color-alt: hsl(var(--hue-color), 80%, 43%);
--second-color: hsl(var(--hue-color), 56%, 12%);
--text-color: hsl(var(--hue-color), 56%, 12%);
--container-color: hsl(var(--hue-color), 0%, 100%);
;
/*===== Fuente y tipografia =====*/
--body-font: 'Poppins', sans-serif;
--big-font-size: 2rem;
--h1-font-size: 1.5rem;
--h2-font-size: 1.25rem;
--h3-font-size: 1.125rem;
--normal-font-size: .938rem;
--medium-font-size: .875rem;
--small-font-size: .813rem;
--smaller-font-size: .75rem;
/*========== Font weight ==========*/
--font-medium: 500;
--font-semi-bold: 600;
/*===== Margins =====*/
--mb-0-25: .25rem;
--mb-2: 1rem;
--mb-4: 2rem;
--mb-5: 2.5rem;
--mb-6: 3rem;
/*===== z index =====*/
--z-tooltip: 10;
--z-back: -10;
--z-fixed: 100;
}
@media screen and (min-width: 968px) {
:root {
--big-font-size: 3.5rem;
--h2-font-size: 2rem;
--normal-font-size: 1rem;
--smaller-font-size: .875rem;
}
}
/*===== BASE =====*/
*,
::before,
::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
background-color: var(--container-color);
}
body {
margin: var(--header-height) 0 0 0;
font-family: var(--body-font);
font-size: var(--normal-font-size);
color: var(--text-color);
background-color: var(--container-color);
}
h1,
h2,
p {
margin: 0;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
a {
text-decoration: none;
}
img {
max-width: 100%;
height: auto;
display: block;
}
/*===== CLASS CSS ===== */
.section-title {
position: relative;
font-size: var(--h2-font-size);
color: var(--first-color);
margin-top: var(--mb-2);
text-align: center;
}
.section-title::after {
position: absolute;
content: '';
width: 64px;
height: 0.18rem;
left: 0;
right: 0;
margin: auto;
top: 2rem;
background-color: var(--first-color);
}
.section {
padding-top: 3rem;
padding-bottom: 2rem;
padding: 2rem 0 4rem;
}
/*===== LAYOUT =====*/
.bd-grid {
max-width: 1024px;
display: grid;
margin-left: var(--mb-2);
margin-right: var(--mb-2);
}
.l-header {
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: var(--z-fixed);
background-color: var(--container-color);
box-shadow: 0 1px 4px rgba(146, 161, 176, 0.15);
}
/*========== Variables Dark theme ==========*/
body.dark-theme {
--first-color: hsl(var(--hue-color), 89%, 60%);
--first-color-alt: hsl(var(--hue-color), 80%, 43%);
--text-color: hsl(var(--hue-color), 89%, 100%);
--second-color: hsl(var(--hue-color), 80%, 40%);
--container-color: hsl(var(--hue-color), 86%, 12%);
}
/*========== Button Dark/Light ==========*/
.change-theme {
position: absolute;
right: 1rem;
top: 1.8rem;
color: var(--text-color);
font-size: 1rem;
cursor: pointer;
}
/*===== NAV =====*/
.nav {
height: var(--header-height);
display: flex;
justify-content: space-between;
align-items: center;
font-weight: var(--font-semi);
}
@media screen and (max-width: 767px) {
.nav__menu {
position: fixed;
top: var(--header-height);
right: -100%;
width: 80%;
height: 100%;
padding: 2rem;
background-color: var(--second-color);
transition: .5s;
}
}
.nav__item {
margin-bottom: var(--mb-4);
}
.nav__link {
position: relative;
color: #fff;
}
.nav__link:hover {
position: relative;
}
.nav__link:hover::after {
position: absolute;
content: '';
width: 100%;
height: 0.18rem;
left: 0;
top: 2rem;
background-color: var(--first-color);
}
.nav__logo {
color: var(--text-color);
}
.nav__toggle {
color: var(--text-color);
font-size: 1.5rem;
cursor: pointer;
}
/*Active menu*/
.active::after {
position: absolute;
content: '';
width: 100%;
height: 0.18rem;
left: 0;
top: 2rem;
background-color: var(--first-color);
}
/*=== Show menu ===*/
.show {
right: 0;
}
/*===== HOME =====*/
.home {
position: relative;
row-gap: 5rem;
padding: 4rem 0 5rem;
}
.home__data {
align-self: center;
}
.home__title {
font-size: var(--big-font-size);
margin-bottom: var(--mb-5);
}
.home__title-color {
color: var(--first-color);
}
.home__social {
display: flex;
flex-direction: column;
}
.home__social-icon {
width: max-content;
margin-bottom: var(--mb-2);
font-size: 1.5rem;
color: var(--text-color);
}
.home__social-icon:hover {
color: var(--first-color);
}
.home__img {
position: absolute;
right: 0;
bottom: 0;
width: 260px;
}
.home__blob {
margin-bottom: 14%;
fill: var(--first-color);
}
.home__blob-img {
transform: scale(1.4);
width: 360px;
}
/*BUTTONS*/
.button {
display: inline-block;
background-color: var(--first-color);
color: #fff;
padding: .75rem 2.5rem;
font-weight: var(--font-semi);
border-radius: .5rem;
transition: .3s;
}
.button:hover {
box-shadow: 0px 10px 36px rgba(0, 0, 0, 0.15);
}
/* ===== ABOUT =====*/
.about__container {
row-gap: 2rem;
text-align: center;
}
.about__subtitle {
margin-bottom: var(--mb-2);
}
.about__img {
justify-self: center;
}
.about__img img {
width: 200px;
border-radius: .5rem;
}
/* ===== SKILLS =====*/
.skills__container {
row-gap: 2rem;
text-align: center;
}
.skills__subtitle {
margin-bottom: var(--mb-2);
}
.skills__text {
margin-bottom: var(--mb-4);
}
.skills__data {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
font-weight: var(--font-semi);
padding: .5rem 1rem;
margin-bottom: var(--mb-4);
border-radius: .5rem;
box-shadow: 0px 4px 25px rgba(14, 36, 49, 0.15);
}
.skills__icon {
font-size: 2rem;
margin-right: var(--mb-2);
color: var(--first-color);
}
.skills__names {
display: flex;
align-items: center;
}
.skills__bar {
position: absolute;
left: 0;
bottom: 0;
background-color: var(--first-color);
height: .25rem;
border-radius: .5rem;
z-index: var(--z-back);
}
.qualities__trust {
width: 100%;
}
.qualities__loyalty {
width: 100%;
}
.qualities__respect {
width: 90%;
}
.qualities__understanding {
width: 90%;
}
.skills__img {
border-radius: .5rem;
}
/* ===== WORK =====*/
.work__container {
row-gap: 2rem;
}
.work__img {
height: 500px;
box-shadow: 0px 4px 25px rgba(14, 36, 49, 0.15);
border-radius: .5rem;
overflow: hidden;
}
.work__img img {
transition: 1s;
}
.work__img img:hover {
transform: scale(1.1);
}
/* ===== CONTACT =====*/
.contact__input {
width: 100%;
font-size: var(--normal-font-size);
font-weight: var(--font-semi);
padding: 1rem;
border-radius: .5rem;
border: 1.5px solid var(--second-color);
outline: none;
margin-bottom: var(--mb-4);
}
.contact__button {
display: block;
border: none;
outline: none;
font-size: var(--normal-font-size);
cursor: pointer;
margin-left: auto;
}
/* WISH */
canvas {
display: block
}
.wish {
position: absolute;
margin-top: 22%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
font-family: "Source Sans Pro";
font-size: 5em;
font-weight: 900;
}
/* ===== FOOTER =====*/
.footer {
background-color: var(--second-color);
color: #fff;
text-align: center;
font-weight: var(--font-semi);
padding: 2rem 0;
}
.footer__title {
font-size: 2rem;
margin-bottom: var(--mb-4);
}
.footer__social {
margin-bottom: var(--mb-4);
}
.footer__icon {
font-size: 1.5rem;
color: #fff;
margin: 0 var(--mb-2);
}
.footer__copy {
font-size: var(--smaller-font-size);
}
/* ===== SCROLL TOP ===== */
.scrolltop {
position: fixed;
right: 1rem;
bottom: -20%;
display: flex;
justify-content: center;
align-items: center;
padding: .3rem;
background: var(--first-color);
border-radius: .4rem;
z-index: var(--z-tooltip);
transition: .4s;
visibility: hidden;
}
.scrolltop:hover {
background-color: var(--first-color-alt);
}
.scrolltop__icon {
font-size: 1.8rem;
color: #fff;
}
/* Show scrolltop */
.show-scroll {
visibility: visible;
bottom: 1.5rem;
}
/* ===== MEDIA QUERIES=====*/
@media screen and (max-width: 320px) {
.home {
row-gap: 2rem;
}
.home__img {
width: 200px;
}
}
@media screen and (min-width: 576px) {
.home {
padding: 4rem 0 2rem;
}
.home__social {
padding-top: 0;
padding-bottom: 2.5rem;
flex-direction: row;
align-self: flex-end;
}
.home__social-icon {
margin-bottom: 0;
margin-right: var(--mb-4);
}
.home__img {
width: 300px;
bottom: 25%;
}
.about__container {
grid-template-columns: repeat(2, 1fr);
align-items: center;
text-align: initial;
}
.skills__container {
grid-template-columns: .7fr;
justify-content: center;
column-gap: 1rem;
}
.work__container {
grid-template-columns: repeat(2, 1fr);
column-gap: 2rem;
padding-top: 2rem;
}
.contact__form {
width: 360px;
padding-top: 2rem;
}
.contact__container {
justify-items: center;
}
}
@media screen and (min-width: 768px) {
body {
margin: 0;
}
.section {
padding-top: 4rem;
padding-bottom: 3rem;
}
.section-title {
margin-bottom: var(--mb-6);
}
.section-title::after {
width: 80px;
top: 3rem;
}
.nav {
height: calc(var(--header-height) + 1.5rem);
}
.nav__list {
display: flex;
padding-top: 0;
}
.nav__item {
margin-left: var(--mb-6);
margin-bottom: 0;
}
.nav__toggle {
display: none;
}
.change-theme {
position: initial;
margin-left: var(--mb-2);
}
.nav__link {
color: var(--text-color);
}
.home {
padding: 8rem 0 2rem;
}
.home__img {
width: 400px;
bottom: 10%;
}
.about__container {
padding-top: 2rem;
}
.about__img img {
width: 300px;
}
.skills__container {
grid-template-columns: repeat(2, 1fr);
column-gap: 2rem;
align-items: center;
text-align: initial;
}
.work__container {
grid-template-columns: repeat(3, 1fr);
column-gap: 2rem;
}
}
@media screen and (min-width: 992px) {
.bd-grid {
margin-left: auto;
margin-right: auto;
}
.home {
padding: 10rem 0 2rem;
}
.home__img {
width: 450px;
}
}
<!--===== WISH =====-->
<section class="wish__section section" id="wish">
<h1 class="wish">Happy Birthday!</h1>
<canvas id="birthday">
</canvas>
</section>
</main>
<!--===== SCROLL REVEAL =====-->
<script src="https://unpkg.com/scrollreveal"></script>
<!--===== MAIN JS =====-->
<!-- script src="assets/js/main.js"></script -->
2
Answers
you can wrap it i div and then use text-align center
I ended up adding
display: flex; justify-content: center; align-items: center;
to.wish__section
with CSS so that the container centers the title for you.I also removed the CSS located in
.wish
related to centering so that the styling didn’t conflict.If you need Happy Birthday to live on two separate lines, add a
<br>
tag in between Happy & Birthday for your title.