What is Food Farmer Finance (FFF) | What is FFF token

In this article, we'll discuss information about the Food Farmer Finance project and FFF token. What is Food Farmer Finance (FFF) | What is FFF token?

FFF is a collective of established DeFi 3.0 innovators, advisors, developers, yield farmers, and investors who have come together to provide the community with a quality offering within the Farming-as-a-Service sector via ownership of FFF tokens.

Food Farmer Finance aims to solve the problems of prior cryptocurrencies and DeFi investments, including yield farming and index funds. Yield farming can be highly lucrative but requires know-how and constant monitoring to succeed, while yield farming remains of interest due to its opportunities. We propose allowing users to participate in a smart contract DeFi hedge fund to produce yields on your behalf.

We see FFF as an asset allocation tool that provides token holders with exposure to yield farming strategies that are otherwise complicated, time-consuming, and high-risk in nature. Within our framework, we manage funds that have been raised via our pre-sale and treasury to provide our holders with exposure to the performance of our strategy and passive income generation.

In our view, this is early-stage adoption of FaaS / Defi 3.0 and we believe this project has a significant advantage in being one of the first movers who are deploying a team of experts with managed investment experience.

In our "Meet the Team" section, you can read further information on our accomplishments and experience to get to know us better.

$FFF

The FFF token represents fractionalized ownership in Food Farmer Finance, a tokenized DeFi hedge fund that offers holders exposure to a range of high-performing strategies such as yield farming. The project's objective is to raise funds via a pre-sale and tax system that is then managed and grown by our internal teams to provide exposure to an appreciating asset base and income stream to holders of the token via claiming reflections and rewards using the FFF Dapp.

Our lead farmer and support team have a track record of success in building current FaaS projects and the deployment and management of treasury balances. Through ownership of FFF tokens, holders receive fractionated exposure to the performance of our treasury and, via our many platforms, have direct access to our educational services, expertise, and community discussion.

Our mandate is to deploy community funds across a robust strategy that offers superior risk management, performance, diversification, and income to alternatives currently available in the market.

Why should you own $FFF?

FFF offers a compelling advantage within the Defi 3.0 / FaaS landscape; at the time of deployment, FFF has the most compelling valuation, and the timing of deployment of funds has been opportunistic given the recent sell-off in the market.

Our team has a track record of success, our holder base is comprised of a diverse range of respected Defi 2.0 projects and fellow FaaS plays, which provides potential holders with a unique level of validation that has been otherwise unseen in the space.

When it comes to trading, the exceptional opportunities in the market are often reserved for those with larger wallets. We aim to provide the community with access to these opportunities through ownership of our tokens.

Our Vision

Our vision is to be the leading Farming-as-a-Service collective across blockchain as a whole, to challenge the legacy financial industry, and offer easy access to the best DeFi exposure available through strategic spot investments, and expert-curated optimization of yield farming across multiple blockchains.

Our decentralized FaaS token shifts fоundаtiоnаl trust away from lеgасу centralized authorities to an easily accessible, transparent, peer-to-peer blосkсhаin thаt is rapid аnd реrmiѕѕiоnlеѕѕ. Unlikе traditional hedge funds.

Our Strategy

FFF strategies include a combination of low, medium, and high-risk strategic investments that are meticulously crafted and planned to detail utilizing every potential arbitrage at hand.

We deploy our treasury over volatile assets and stable coins. FFF aims to capture the DeFi equivalent to the risk-adjusted investment approach that Ray Dalio co-chairs at Bridgewater Associates.

Through our existing relationships within DeFi, we intend to align our project with some of the best minds in the industry to continue to provide our community with access to premium opportunities.

Our Goals

Our goal is to be the frontier solution within the FaaS industry and lead the charge to a decentralized self-governed future.

To grow FFF to become the DeFi equivalent to leading TradFi asset management providers such as Blackrock, Fidelity, NIKKO AM, Vanguard.

To inspire individuals and businesses to join us on our mission towards a decentralized tomorrow.

To create something truly remarkable.

Tokenomics

Distribution of FFF tokens, and vesting schedule.

1 FFF = 1 FFF

Presale priced at 0.001 and public sale priced at 0.001, strict vesting rules in place for founders and presale participants via contract.

Team allocation, presale, and vesting

The total amount of FFF tokens is 1,000,000,000 at launch, we reserve the right to buy back and burn FFF tokens.

We are implementing a vesting schedule internally and against all presale allocations, with the following breakdown:

Team

A total of 10% of the supply is dedicated towards the team and is vested for twelve months.

Presale

A total of 60% of supply is dedicated towards presale, a vesting schedule is applied against all presale allocations, with the following breakdown:

33.3% available at public launch.

33.3% available at 1 month after launch.

33.3% available at 2 months after launch.

Public launch

30% available at public launch.

Utilization of funds

Funds raised via our pre-sale will be allocated on a 50 / 50 basis across our treasury and liquidity pool. This will provide us with an initial farming wallet of roughly 125 ETH and $300,000 USD in liquidity in addition to the 300,000,000 tokens we have allocated from the free float.

Taxation distribution

Every transaction is liable to 12% taxation and is distributed as follows:

8% Treasury

2% Reflections

2% Liquidity pool

In addition to the above, we also reserve the right to buy back the FFF token and burn it supporting and increasing the price floor while depreciating the supply.

Reflection rewards

Frictionless, static reflections accumulate by simply holding your $FFF token and feature an innovative hold-farming reward structure that stands out from the standard. This function aims to eliminate token dependencies and reward participation on top of profits.

Reflection rewards are claimable via our Dapp, and users have the option to either reinvest the rewards as FFF tokens (converted from ETH to FFF) or claim the ETH to their wallet directly.

Automatic liquidity acquisition

Liquidity is crucial in any trading environment. By definition, decentralized liquidity is the accessibility of tokens operated, controlled, and hosted by a decentralized exchange governed by a smart contract.

This mechanism acts as a resistance securing the volume of FFF; the added liquidity pool creates stability from the supplied liquidity by adding the Tax to the overall liquidity of the token. As the pool increases, the price stability mirrors this with the benefit of a substantial price floor and cushion for holders.

Treasury

Money in the treasury is used to farm across multiple chains and return the profits as dividends back to $FFF holders.

ROI

Return on investment

Core thesis

One of the core drivers behind creating this project was to offer the community a vehicle that provides a high level of ROI to holders. We intend to do this at Food farmer financial via three avenues:

Treasury growth = Market capitalization growth

We aim to grow our treasury rapidly. While there is no correlation between treasury growth and token price, we believe the market will price FFF tokens based on the underlying performance and value of the holdings and may even apply basic run-rate metrics to the project, treasury and market cap intends to provide holders with ROI via token price appreciation.

Staking

Staking will be available early, and we intend to incentivize users to provide liquidity with additional rewards to any participants in our FFF / ETH liquidity pool that shall be accessible on Uniswap. These rewards will be paid out in ETH that is claimable within our Dapp.

Reflections

Two percent of transactions reflect automatically to all FFF participants. Reflection rewards are claimable via our Dapp, and users have the option to either reinvest the rewards as FFF tokens (converted from ETH to FFF) or claim the ETH to their wallet directly.

Summary

We will continue to build out the utility of the token over time, with the view to operate across multiple chains, in the short term, our goals include launching across FTM, AVAX & BSC chains. There will be additional stores of value generated and additional avenues for further ROI as the project matures.

Liquidity Pool

We have elected to launch staking as one of the first items on our roadmap. One of the headwinds we have seen in other projects is the lack of funds available in LPs and the inability to deploy across multiple chains rapidly.

We will have an FFF/ETH pool available on Uniswap to provide investors with a location to stake their FFF tokens and generate a dynamic APR.

We intend to apply the same model as we deploy across multiple blockchains, and our first targets include Fantom, Avalanche, and Binance Smart Chain.

How and Where to Buy FFF token?

FFF token is now live on the ETH mainnet. The token address for FFF is 0xc16b2419494ae0604432297d40cdf0e8d68de8d6. Be cautious not to purchase any other token with a smart contract different from this one (as this can be easily faked). We strongly advise to be vigilant and stay safe throughout the launch. Don’t let the excitement get the best of you.

Just be sure you have enough ETH in your wallet to cover the transaction fees.

You will have to first buy one of the major cryptocurrencies, usually either Bitcoin (BTC), Ethereum (ETH), Tether (USDT), Binance (BNB)…

We will use Binance Exchange here as it is one of the largest crypto exchanges that accept fiat deposits.

Once you finished the KYC process. You will be asked to add a payment method. Here you can either choose to provide a credit/debit card or use a bank transfer, and buy one of the major cryptocurrencies, usually either Bitcoin (BTC), Ethereum (ETH), Tether (USDT), Binance (BNB)…

☞ SIGN UP ON BINANCE

Step by Step Guide : What is Binance | How to Create an account on Binance (Updated 2022)

Next step

You need a wallet address to Connect to Uniswap Decentralized Exchange, we use Metamask wallet

If you don’t have a Metamask wallet, read this article and follow the steps

What is Metamask wallet | How to Create a wallet and Use

Transfer $ETH to your new Metamask wallet from Binance wallet

Next step

Connect Metamask Wallet to Uniswap Decentralized Exchange and Buy, Swap FFF token

Contract: 0xc16b2419494ae0604432297d40cdf0e8d68de8d6

Read more: What is Uniswap | Beginner's Guide on How to Use Uniswap

The top exchange for trading in FFF token is currently: Uniswap (V2)

Top exchanges for token-coin trading. Follow instructions and make unlimited money

BinanceBittrexPoloniexBitfinexHuobiMXCProBITGate.ioCoinbase

🔺DISCLAIMER: The Information in the post isn’t financial advice, is intended FOR GENERAL INFORMATION PURPOSES ONLY. Trading Cryptocurrency is VERY risky. Make sure you understand these risks and that you are responsible for what you do with your money.

🔥 If you’re a beginner. I believe the article below will be useful to you ☞ What You Should Know Before Investing in Cryptocurrency - For Beginner

⭐ ⭐ ⭐The project is of interest to the community ☞ **-----https://geekcash.org-----**⭐ ⭐ ⭐

Find more information FFF token ☞ Website

I hope this post will help you. Don't forget to leave a like, comment and sharing it with others. Thank you!

#bitcoin #cryptocurrency

What is GEEK

Buddha Community

What is Food Farmer Finance (FFF) | What is FFF token
Rachel Cole

Rachel Cole

1652925979

Create Your Own Modern Portfolio Website using HTML, CSS and JavaScrip

🔥 Make a portfolio website with HTML CSS JS [ CSS Timeline / With Source Code ]

If you are a beginner or a pro. This video is for everyone who want to make his/her portfolio an outstanding one. In this tutorial, you’ll learn to create your own modern looking portfolio website using HTML, CSS and JS. In the video, you’ll create smooth transition on navigations, you’ll create CSS timeline to showcase your education and experience, you’ll make a separate section for your project with a cool hover effect. You must make this portfolio to impress your recruiter.

⏰ Timestamps ⏰ 
————————————
00:00 - Intro
00:16 - Portfolio - Demo
02:24 - Portfolio - Navbar
07:20 - Portfolio - Home section
11:11 - Portfolio - Project Section
22:05 - Portfolio - Naviagtion (app.js)
25:06 - Portfolio - About Section
31:01 - Portfolio - Skills section
39:12 - Portfolio - CSS Timeline
49:17 - Portfolio - Contact Section
57:07 - Great Work! We are done👏


Navbar

So let's start, to create navbar first write the HTML basic template and link style.css and app.js file to index.html file. After done with all of this. Create navbar.
 

<!-- navbar -->
<nav class="navbar">
    <ul class="link-group">
        <li class="link active"><a href="#">home</a></li>
        <li class="link"><a href="#">projects</a></li>
        <li class="link"><a href="#">about</a></li>
        <li class="link"><a href="#">contact</a></li>
    </ul>
</nav>

Okay we are done with HTMl, so add some style to it also.

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body{
    width: 100%;
    max-width: 1400px;
    display: block;
    margin: auto;
    min-height: 100vh;
    background: #191919;
    font-family: sans-serif;
}

.navbar{
    width: 100%;
    position: fixed;
    top: 0;
    left: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 9;
    background: #1a1a1a;
}

.link-group{
    list-style: none;
    display: flex;
}

.link a{
    color: #fff;
    opacity: 0.5;
    text-decoration: none;
    text-transform: capitalize;
    padding: 10px 30px;
    margin: 0 20px;
    line-height: 80px;
    transition: .5s;
    font-size: 20px;
}

.link a:hover, .link.active a{
    opacity: 1;
}

After done with this, you'll probably see something like this.

Portfolio Website - Navbar

Okay, so with that we are done with navbar. So let's move on to our home section

home section

To create home section code this HTML structure after navbar element.

<!-- home section -->

<section class="home-section active">
    <h1 class="hero-heading">hello, i am <br> kunaal</h1>
    <img src="img/home.png" class="home-img" alt="">
</section>

And give it some styles.

.home-section{
    width: 100%;
    height: 100vh;
    padding: 0 150px;
    display: flex;
    align-items: center;
    position: relative;
    top: 0;
    opacity: 0;
    transition: 1s;
}

.hero-heading{
    color: #fff;
    font-size: 120px;
    text-transform: capitalize;
    font-weight: 300;
}

.home-img{
    position: absolute;
    top: 0;
    right: 0;
    height: 100vh;
    width: 50%;
    object-fit: cover;
    opacity: 0.2;
}

If you see the above code, you'll see position: relative and top: 0 under .home-section. These properties are important while navigation, cause how will our navigation work is little complex. All of our sections (home, project, about, contact) all of these will have position: fixed because of this, all sections will be on top of each other. And we'll use active class to indicate the active section. Using active class we'll set section's position's to relative along with its opacity to 1. This is how our navigation will work. Isn't is complicated ??

Output

Output

So, once you are done with home section make sure you change its position to fixed from relative.

.home-section{
    /* previous styles */
    position: fixed;
}

Then make active class styles.

.home-section.active,
.project-section.active,
.about-section.active,
.contact-section.active{
    position: relative;
    opacity: 1;
    z-index: 8;
}

You can see I have added each and every section here in order to make smooth navigation.

Project section

Now, let's make project section. For that code this HTML.

<!-- project section -->
<section class="project-section">
    <h1 class="project-heading">some of my projects</h1>
    <div class="project-container">
        <div class="project-card">
            <img src="img/project-1.png" class="project-img" alt="">
            <div class="project-content">
                <h1 class="project-title">project 01</h1>
                <p class="project-info">
                    Lorem ipsum dolor, sit amet consectetur adipisicing elit. Impedit vitae delectus cumque repudiandae aliquam optio accusamus natus nobis! Nam, sunt?
                </p>
                <div class="project-btn-grp">
                    <button class="project-btn github">github repo</button>
                    <button class="project-btn live">see live</button>
                </div>
            </div>
        </div>
        // +3 more cards
    </div>
</section>

Also style it.

/* project-section */

.project-section{
    width: 100%;
    min-height: 100vh;
    padding: 150px 100px 100px;
    position: fixed;
    top: 0;
    transition: 1s;
    opacity: 0;
}

.project-heading{
    font-size: 100px;
    background: #252525;
    text-transform: capitalize;
    text-align: center;
    margin-bottom: 50px;
    color: #1a1a1a;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-stroke: 8px transparent;
}

.project-container{
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-gap: 100px;
}

.project-card{
    height: 400px;
    position: relative;
}

.project-img{
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    object-fit: cover;
    transition: .5s;
}

.project-content{
    position: relative;
    padding: 40px;
    color: #fff;
    transition: .5s;
    opacity: 0;
}

.project-title{
    font-size: 50px;
    text-transform: capitalize;
    text-align: center;
    font-weight: 300;
}

.project-info{
    margin: 40px;
    font-size: 20px;
    line-height: 30px;
    text-align: center;
}

.project-btn-grp{
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-gap: 20px;
}

.project-btn{
    height: 40px;
    text-transform: capitalize;
    font-size: 18px;
    border: none;
    background: #000;
    color: #fff;
    cursor: pointer;
}

.project-btn.live{
    background: none;
    border: 2px solid #fff;
}

.project-card:hover .project-img{
    filter: blur(20px);
}

.project-card:hover .project-content{
    opacity: 1;
}

In the above code, I have already added fixed position to project-section and defined its opacity to 0. But for you in order to see the output. make sure you add active class in project-section like this.

<section class="project-section active">

Output [ With hover effect ]

Project section

Navigation

Before going forward, let's make the navigation system first. For that code this inside app.js file.

const links = document.querySelectorAll('.link');
const sections = document.querySelectorAll('section');

let activeLink = 0;

links.forEach((link, i) => {
    link.addEventListener('click', () => {
        if(activeLink != i){
            links[activeLink].classList.remove('active');
            link.classList.add('active');
            sections[activeLink].classList.remove('active');

            setTimeout(() => {
                activeLink = i;
                sections[i].classList.add('active');
            }, 1000);
        }
    })
})

In the above code, first I am selecting all the links and sections. After that, I defined activeLink this variable will track the current active section or link. After that, I used forEach method to loop through all the links. Inside that I am access individual link and its index.

Inside it first, I am adding click event to link using addEventListener. Then I used a simple condition to make sure user is not clicking on the active link. After that, I am removing the active class from the current active link using classList.remove and adding active class to the clicked link using classList.add. I am doing the same to remove the active class from the active section.

Once done with that, I am using setTimeout to add a 1s delay in executing the below codes. Inside the timeout, it is just simply adding the active class again.

You might see the navigation as a very easy one, but it was the second hardest thing to make in this project😅

About section.

Now, let's create the about section. Honestly, my favourite section in this entire website is this about section. Our about section has everything, it has skills section, and also a education timeline.

To create about section, code this after project section.

<!-- about section -->
<section class="about-section">
    <div class="about">
        <div class="about-img-container">
            <img src="img/home.png" class="about-img" alt="">
            <button class="download-cv-btn">downlaod cv</button>
        </div>
        <p class="about-info">Lorem ipsum.....</p>
    </div>
</section>

And style it.

/* about-section */

.about-section{
    width: 100%;
    min-height: 100vh;
    padding: 150px 100px 0;
    position: fixed;
    top: 0;
    opacity: 0;
    transition: 1s;
}

.about{
    width: 100%;
    display: grid;
    grid-template-columns: 30% 65%;
    grid-gap: 40px;
}

.about-img-container{
    position: relative;
}

.about-info{
    color: #fff;
    opacity: 0.6;
    font-size: 20px;
    line-height: 40px;
}

.about-img{
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 20px;
}

.download-cv-btn{
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    padding: 10px 20px;
    color: #fff;
    border: none;
    font-size: 16px;
    text-transform: capitalize;
    cursor: pointer;
    transition: .5s;
    background: rgba(0, 0, 0, 0.5);
}

.download-cv-btn:hover{
    background: #000;
}

Again you might not see anything, make sure to add active class to about-section and remove it from all other sections.

Output

about section

So, now shall we create the skills section ? Well in our skills section I do not have any skill progress bar which is I think is most used thing in the portfolio. But I think its the worst thing to have. I somewhere read on internet that the progress bar might look awesome to you, but let say it know python 90% and you add it to your website saying, you know 90% of python. There is a change that your client think you know 90% python so maybe you don't know the advance topic although you know the advance topics too. So its create a confusion. Well its just a preference. Anyway, let's make the skills section.

<!-- skills -->
<div class="skill-section">
    <h1 class="heading">skills</h1>
    <div class="skills-container">
        <div class="skill-card">
            <img src="img/html.png" class="skill-img" alt="">
            <div class="skill-level">98%</div>
            <h1 class="skill-name">HTML</h1>
            <p class="skill-info">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Consequatur, delectus!</p>
        </div>
        // +4 more cards
    </div>
</div>

Code the above code under about-section element and style them.

/* skills */

.skill-section{
    position: relative;
    margin: 100px 0;
}

.heading{
    text-align: center;
    font-size: 60px;
    color: #fff;
    text-transform: capitalize;
    font-weight: 300;
    margin-bottom: 100px;
}

.skills-container{
    width: 95%;
    margin: auto;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 100px;
    color: #fff;
}

.skill-card{
    position: relative;
}

.skill-img{
    display: block;
    margin: auto;
    height: 200px;
}

.skill-name{
    font-size: 30px;
    font-weight: 300;
    text-align: center;
    text-transform: capitalize;
    margin: 30px 0 20px;
}

.skill-info{
    text-align: center;
    opacity: 0.5;
    font-size: 18px;
    line-height: 30px;
}

.skill-level{
    position: absolute;
    top: 80px;
    right: 0;
    width: 150px;
    height: 150px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 22px;
    border-radius: 50%;
    border: 10px solid;
}

.skill-card:nth-child(1) .skill-level{
    background: #ff4f4f28;
    border-color: #ff4f4f;
    color: #ff4f4f;
}

.skill-card:nth-child(2) .skill-level{
    background: #4fa0ff28;
    border-color: #4fa0ff;
    color: #4fa0ff;
}

.skill-card:nth-child(3) .skill-level{
    background: #ffed4f28;
    border-color: #ffed4f;
    color: #ffed4f;
}

.skill-card:nth-child(4) .skill-level{
    background: #52ff4f28;
    border-color: #52ff4f;
    color: #52ff4f;
}

.skill-card:nth-child(5) .skill-level{
    background: #4fdfff28;
    border-color: #4fdfff;
    color: #4fdfff;
}

Output

Skill section

And now the hardest thing, CSS timeline. It was little hard for me to make at first, but I tried my best not to use lot of code to achieve the goal.

<!-- timeline -->
<div class="timeline">
    <h1 class="heading">education and experience</h1>
    <div class="card">
        <div class="card-body">
            <h1 class="card-title">2000-2002</h1>
            <p class="card-detail">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Architecto sequi recusandae laborum ipsam dignissimos nostrum vitae provident officia, consectetur ab accusantium corrupti exercitationem temporibus repellat non magni cupiditate ea reprehenderit.</p>
        </div>
    </div>
    //+4 more cards
</div>

Make sure to add these codes inside about-section also.

/* timeline */

.timeline{
    display: block;
    width: 80%;
    margin: 150px auto;
}

.timeline .heading{
    margin-bottom: 150px;
}

.card{
    width: 45%;
    padding: 30px;
    border-radius: 10px;
    color: #fff;
    display: block;
    margin: -80px 0;
    position: relative;
    background: #f00;
}

.card:nth-child(even){
    margin-left: auto;
}

.card:nth-child(even):before{
    content: '';
    position: absolute;
    left: -15%;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    border: 5px solid #191919;
    border-radius: 50%;
}

.card:nth-child(even):after{
    content: '';
    position: absolute;
    left: -8.5%;
    top: 50%;
    transform: translateY(-50%);
    width: 7%;
    height: 2px;
    background: #fff;
    z-index: -1;
}

.card:nth-child(odd):before{
    content: '';
    position: absolute;
    right: -13%;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    border: 5px solid #191919;
    border-radius: 50%;
}

.card:nth-child(odd):after{
    content: '';
    position: absolute;
    right: -8.5%;
    top: 50%;
    transform: translateY(-50%);
    width: 7%;
    height: 2px;
    background: #fff;
    z-index: -1;
}

.card:nth-child(2), .card:nth-child(2):before{
    background: #ff4f4f;
}
.card:nth-child(3), .card:nth-child(3):before{
    background: #ffb84f;
}
.card:nth-child(4), .card:nth-child(4):before{
    background: #3dca5c;
}
.card:nth-child(5), .card:nth-child(5):before{
    background: #565252;
}
.card:nth-child(6), .card:nth-child(6):before{
    background: #4fa0ff;
}

.card:nth-child(even) .card-body:before{
    content: '';
    position: absolute;
    left: -12%;
    top: 0;
    width: 0px;
    height: 100%;
    border: 1px dashed #fff;
    z-index: -1;
}

.card-title{
    font-size: 30px;
    font-weight: 300;
    margin-bottom: 20px;
}

Output

timeline

Contact section

Anddddddd, the last part contact section. Let's create this also.

<!-- contact section -->
<section class="contact-section">
    <form class="contact-form">
        <input type="text" name="name" id="name" autocomplete="off" placeholder="name">
        <input type="text" name="email" id="email" autocomplete="off" placeholder="email">
        <textarea name="msg" id="msg" placeholder="message" autocomplete="off"></textarea>
        <button type="submit" class="form-submit-btn">contact</button>
    </form>
    <!-- map -->
    <div class="map">
        <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d448181.163742937!2d76.81306771991275!3d28.647279935262464!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x390cfd5b347eb62d%3A0x37205b715389640!2sDelhi!5e0!3m2!1sen!2sin!4v1639489002410!5m2!1sen!2sin" width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy"></iframe>
    </div>
</section>

By the way, the above iframe code is the google map embed link. You can get it using google map.

.contact-section{
    position: absolute;
    top: 0;
    opacity: 0;
    transition: 1s;
    padding: 100px 150px;
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-gap: 50px;
}

.contact-form input, .contact-form textarea{
    width: 100%;
    height: 40px;
    background: rgba(255, 255, 255, 0.2);
    border: 1px solid #fff;
    margin-bottom: 30px;
    border-radius: 5px;
    text-transform: capitalize;
    color: #fff;
    padding: 5px 10px;
}

::placeholder{
    color: #fff;
}

#msg{
    height: 280px;
    resize: none;
    font-family: sans-serif;
}

.form-submit-btn{
    background: #ff4f4f;
    color: #fff;
    text-transform: capitalize;
    padding: 15px 40px;
    display: block;
    margin: auto;
    border: none;
    border-radius: 10px;
    cursor: pointer;
}

.map{
    width: 100%;
    height: 100%;
    padding: 10px;
    border: 2px solid #fff;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 10px;
}

.map iframe{
    width: 100%;
    height: 100%;
    border-radius: 5px;
}

Output

Contact section

So, that's it. Great work guys. We are done with the portfolio.

📌 Download Images - https://drive.google.com/drive/folders/1z8ZdauuOMkoYoNWx5NlxjlQbqLHGpPhN?usp=sharing   

#html #css #javascript #webdev #programming 

How to Create a Quiz Application with Timer using HTML CSS & JavaScrip

In this guide you’ll learn how to Create a Quiz Application with Timer using HTML CSS & JavaScript.

To create a Quiz Application with Timer using HTML CSS & JavaScript. First, you need to create four Files one HTML File, CSS File and the other two are JavaScript files.

1: First, create an HTML file with the name of index.html

 

<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Awesome Quiz App | Codequs</title>
    <link rel="stylesheet" href="style.css">
    <!-- FontAweome CDN Link for Icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"/>
</head>
<body>
    <!-- start Quiz button -->
    <div class="start_btn"><button>Start Quiz</button></div>
    <!-- Info Box -->
    <div class="info_box">
        <div class="info-title"><span>Some Rules of this Quiz</span></div>
        <div class="info-list">
            <div class="info">1. You will have only <span>15 seconds</span> per each question.</div>
            <div class="info">2. Once you select your answer, it can't be undone.</div>
            <div class="info">3. You can't select any option once time goes off.</div>
            <div class="info">4. You can't exit from the Quiz while you're playing.</div>
            <div class="info">5. You'll get points on the basis of your correct answers.</div>
        </div>
        <div class="buttons">
            <button class="quit">Exit Quiz</button>
            <button class="restart">Continue</button>
        </div>
    </div>
    <!-- Quiz Box -->
    <div class="quiz_box">
        <header>
            <div class="title">Awesome Quiz Application</div>
            <div class="timer">
                <div class="time_left_txt">Time Left</div>
                <div class="timer_sec">15</div>
            </div>
            <div class="time_line"></div>
        </header>
        <section>
            <div class="que_text">
                <!-- Here I've inserted question from JavaScript -->
            </div>
            <div class="option_list">
                <!-- Here I've inserted options from JavaScript -->
            </div>
        </section>
        <!-- footer of Quiz Box -->
        <footer>
            <div class="total_que">
                <!-- Here I've inserted Question Count Number from JavaScript -->
            </div>
            <button class="next_btn">Next Que</button>
        </footer>
    </div>
    <!-- Result Box -->
    <div class="result_box">
        <div class="icon">
            <i class="fas fa-crown"></i>
        </div>
        <div class="complete_text">You've completed the Quiz!</div>
        <div class="score_text">
            <!-- Here I've inserted Score Result from JavaScript -->
        </div>
        <div class="buttons">
            <button class="restart">Replay Quiz</button>
            <button class="quit">Quit Quiz</button>
        </div>
    </div>
    <!-- Inside this JavaScript file I've inserted Questions and Options only -->
    <script src="js/questions.js"></script>
    <!-- Inside this JavaScript file I've coded all Quiz Codes -->
    <script src="js/script.js"></script>
</body>
</html>
</html>

 

2: Second, create a CSS file with the name of style.css

 

/* importing google fonts */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Poppins', sans-serif;
}
body{
    background: #007bff;
}
::selection{
    color: #fff;
    background: #007bff;
}
.start_btn,
.info_box,
.quiz_box,
.result_box{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 
                0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.info_box.activeInfo,
.quiz_box.activeQuiz,
.result_box.activeResult{
    opacity: 1;
    z-index: 5;
    pointer-events: auto;
    transform: translate(-50%, -50%) scale(1);
}
.start_btn button{
    font-size: 25px;
    font-weight: 500;
    color: #007bff;
    padding: 15px 30px;
    outline: none;
    border: none;
    border-radius: 5px;
    background: #fff;
    cursor: pointer;
}
.info_box{
    width: 540px;
    background: #fff;
    border-radius: 5px;
    transform: translate(-50%, -50%) scale(0.9);
    opacity: 0;
    pointer-events: none;
    transition: all 0.3s ease;
}
.info_box .info-title{
    height: 60px;
    width: 100%;
    border-bottom: 1px solid lightgrey;
    display: flex;
    align-items: center;
    padding: 0 30px;
    border-radius: 5px 5px 0 0;
    font-size: 20px;
    font-weight: 600;
}
.info_box .info-list{
    padding: 15px 30px;
}
.info_box .info-list .info{
    margin: 5px 0;
    font-size: 17px;
}
.info_box .info-list .info span{
    font-weight: 600;
    color: #007bff;
}
.info_box .buttons{
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 0 30px;
    border-top: 1px solid lightgrey;
}
.info_box .buttons button{
    margin: 0 5px;
    height: 40px;
    width: 100px;
    font-size: 16px;
    font-weight: 500;
    cursor: pointer;
    border: none;
    outline: none;
    border-radius: 5px;
    border: 1px solid #007bff;
    transition: all 0.3s ease;
}
.quiz_box{
    width: 550px;
    background: #fff;
    border-radius: 5px;
    transform: translate(-50%, -50%) scale(0.9);
    opacity: 0;
    pointer-events: none;
    transition: all 0.3s ease;
}
.quiz_box header{
    position: relative;
    z-index: 2;
    height: 70px;
    padding: 0 30px;
    background: #fff;
    border-radius: 5px 5px 0 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    box-shadow: 0px 3px 5px 1px rgba(0,0,0,0.1);
}
.quiz_box header .title{
    font-size: 20px;
    font-weight: 600;
}
.quiz_box header .timer{
    color: #004085;
    background: #cce5ff;
    border: 1px solid #b8daff;
    height: 45px;
    padding: 0 8px;
    border-radius: 5px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 145px;
}
.quiz_box header .timer .time_left_txt{
    font-weight: 400;
    font-size: 17px;
    user-select: none;
}
.quiz_box header .timer .timer_sec{
    font-size: 18px;
    font-weight: 500;
    height: 30px;
    width: 45px;
    color: #fff;
    border-radius: 5px;
    line-height: 30px;
    text-align: center;
    background: #343a40;
    border: 1px solid #343a40;
    user-select: none;
}
.quiz_box header .time_line{
    position: absolute;
    bottom: 0px;
    left: 0px;
    height: 3px;
    background: #007bff;
}
section{
    padding: 25px 30px 20px 30px;
    background: #fff;
}
section .que_text{
    font-size: 25px;
    font-weight: 600;
}
section .option_list{
    padding: 20px 0px;
    display: block;   
}
section .option_list .option{
    background: aliceblue;
    border: 1px solid #84c5fe;
    border-radius: 5px;
    padding: 8px 15px;
    font-size: 17px;
    margin-bottom: 15px;
    cursor: pointer;
    transition: all 0.3s ease;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
section .option_list .option:last-child{
    margin-bottom: 0px;
}
section .option_list .option:hover{
    color: #004085;
    background: #cce5ff;
    border: 1px solid #b8daff;
}
section .option_list .option.correct{
    color: #155724;
    background: #d4edda;
    border: 1px solid #c3e6cb;
}
section .option_list .option.incorrect{
    color: #721c24;
    background: #f8d7da;
    border: 1px solid #f5c6cb;
}
section .option_list .option.disabled{
    pointer-events: none;
}
section .option_list .option .icon{
    height: 26px;
    width: 26px;
    border: 2px solid transparent;
    border-radius: 50%;
    text-align: center;
    font-size: 13px;
    pointer-events: none;
    transition: all 0.3s ease;
    line-height: 24px;
}
.option_list .option .icon.tick{
    color: #23903c;
    border-color: #23903c;
    background: #d4edda;
}
.option_list .option .icon.cross{
    color: #a42834;
    background: #f8d7da;
    border-color: #a42834;
}
footer{
    height: 60px;
    padding: 0 30px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-top: 1px solid lightgrey;
}
footer .total_que span{
    display: flex;
    user-select: none;
}
footer .total_que span p{
    font-weight: 500;
    padding: 0 5px;
}
footer .total_que span p:first-child{
    padding-left: 0px;
}
footer button{
    height: 40px;
    padding: 0 13px;
    font-size: 18px;
    font-weight: 400;
    cursor: pointer;
    border: none;
    outline: none;
    color: #fff;
    border-radius: 5px;
    background: #007bff;
    border: 1px solid #007bff;
    line-height: 10px;
    opacity: 0;
    pointer-events: none;
    transform: scale(0.95);
    transition: all 0.3s ease;
}
footer button:hover{
    background: #0263ca;
}
footer button.show{
    opacity: 1;
    pointer-events: auto;
    transform: scale(1);
}
.result_box{
    background: #fff;
    border-radius: 5px;
    display: flex;
    padding: 25px 30px;
    width: 450px;
    align-items: center;
    flex-direction: column;
    justify-content: center;
    transform: translate(-50%, -50%) scale(0.9);
    opacity: 0;
    pointer-events: none;
    transition: all 0.3s ease;
}
.result_box .icon{
    font-size: 100px;
    color: #007bff;
    margin-bottom: 10px;
}
.result_box .complete_text{
    font-size: 20px;
    font-weight: 500;
}
.result_box .score_text span{
    display: flex;
    margin: 10px 0;
    font-size: 18px;
    font-weight: 500;
}
.result_box .score_text span p{
    padding: 0 4px;
    font-weight: 600;
}
.result_box .buttons{
    display: flex;
    margin: 20px 0;
}
.result_box .buttons button{
    margin: 0 10px;
    height: 45px;
    padding: 0 20px;
    font-size: 18px;
    font-weight: 500;
    cursor: pointer;
    border: none;
    outline: none;
    border-radius: 5px;
    border: 1px solid #007bff;
    transition: all 0.3s ease;
}
.buttons button.restart{
    color: #fff;
    background: #007bff;
}
.buttons button.restart:hover{
    background: #0263ca;
}
.buttons button.quit{
    color: #007bff;
    background: #fff;
}
.buttons button.quit:hover{
    color: #fff;
    background: #007bff;
}

 

3: Last, create a JavaScript file with the name of questions.js

 

// creating an array and passing the number, questions, options, and answers
let questions = [
    {
    numb: 1,
    question: "What does HTML stand for?",
    answer: "Hyper Text Markup Language",
    options: [
      "Hyper Text Preprocessor",
      "Hyper Text Markup Language",
      "Hyper Text Multiple Language",
      "Hyper Tool Multi Language"
    ]
  },
    {
    numb: 2,
    question: "What does CSS stand for?",
    answer: "Cascading Style Sheet",
    options: [
      "Common Style Sheet",
      "Colorful Style Sheet",
      "Computer Style Sheet",
      "Cascading Style Sheet"
    ]
  },
    {
    numb: 3,
    question: "What does PHP stand for?",
    answer: "Hypertext Preprocessor",
    options: [
      "Hypertext Preprocessor",
      "Hypertext Programming",
      "Hypertext Preprogramming",
      "Hometext Preprocessor"
    ]
  },
    {
    numb: 4,
    question: "What does SQL stand for?",
    answer: "Structured Query Language",
    options: [
      "Stylish Question Language",
      "Stylesheet Query Language",
      "Statement Question Language",
      "Structured Query Language"
    ]
  },
    {
    numb: 5,
    question: "What does XML stand for?",
    answer: "eXtensible Markup Language",
    options: [
      "eXtensible Markup Language",
      "eXecutable Multiple Language",
      "eXTra Multi-Program Language",
      "eXamine Multiple Language"
    ]
  },
  // you can uncomment the below codes and make duplicate as more as you want to add question
  // but remember you need to give the numb value serialize like 1,2,3,5,6,7,8,9.....
  //   {
  //   numb: 6,
  //   question: "Your Question is Here",
  //   answer: "Correct answer of the question is here",
  //   options: [
  //     "Option 1",
  //     "option 2",
  //     "option 3",
  //     "option 4"
  //   ]
  // },
];

 

4: Last, create a JavaScript file with the name of script.js

 

//selecting all required elements
const start_btn = document.querySelector(".start_btn button");
const info_box = document.querySelector(".info_box");
const exit_btn = info_box.querySelector(".buttons .quit");
const continue_btn = info_box.querySelector(".buttons .restart");
const quiz_box = document.querySelector(".quiz_box");
const result_box = document.querySelector(".result_box");
const option_list = document.querySelector(".option_list");
const time_line = document.querySelector("header .time_line");
const timeText = document.querySelector(".timer .time_left_txt");
const timeCount = document.querySelector(".timer .timer_sec");
// if startQuiz button clicked
start_btn.onclick = ()=>{
    info_box.classList.add("activeInfo"); //show info box
}
// if exitQuiz button clicked
exit_btn.onclick = ()=>{
    info_box.classList.remove("activeInfo"); //hide info box
}
// if continueQuiz button clicked
continue_btn.onclick = ()=>{
    info_box.classList.remove("activeInfo"); //hide info box
    quiz_box.classList.add("activeQuiz"); //show quiz box
    showQuetions(0); //calling showQestions function
    queCounter(1); //passing 1 parameter to queCounter
    startTimer(15); //calling startTimer function
    startTimerLine(0); //calling startTimerLine function
}
let timeValue =  15;
let que_count = 0;
let que_numb = 1;
let userScore = 0;
let counter;
let counterLine;
let widthValue = 0;
const restart_quiz = result_box.querySelector(".buttons .restart");
const quit_quiz = result_box.querySelector(".buttons .quit");
// if restartQuiz button clicked
restart_quiz.onclick = ()=>{
    quiz_box.classList.add("activeQuiz"); //show quiz box
    result_box.classList.remove("activeResult"); //hide result box
    timeValue = 15; 
    que_count = 0;
    que_numb = 1;
    userScore = 0;
    widthValue = 0;
    showQuetions(que_count); //calling showQestions function
    queCounter(que_numb); //passing que_numb value to queCounter
    clearInterval(counter); //clear counter
    clearInterval(counterLine); //clear counterLine
    startTimer(timeValue); //calling startTimer function
    startTimerLine(widthValue); //calling startTimerLine function
    timeText.textContent = "Time Left"; //change the text of timeText to Time Left
    next_btn.classList.remove("show"); //hide the next button
}
// if quitQuiz button clicked
quit_quiz.onclick = ()=>{
    window.location.reload(); //reload the current window
}
const next_btn = document.querySelector("footer .next_btn");
const bottom_ques_counter = document.querySelector("footer .total_que");
// if Next Que button clicked
next_btn.onclick = ()=>{
    if(que_count < questions.length - 1){ //if question count is less than total question length
        que_count++; //increment the que_count value
        que_numb++; //increment the que_numb value
        showQuetions(que_count); //calling showQestions function
        queCounter(que_numb); //passing que_numb value to queCounter
        clearInterval(counter); //clear counter
        clearInterval(counterLine); //clear counterLine
        startTimer(timeValue); //calling startTimer function
        startTimerLine(widthValue); //calling startTimerLine function
        timeText.textContent = "Time Left"; //change the timeText to Time Left
        next_btn.classList.remove("show"); //hide the next button
    }else{
        clearInterval(counter); //clear counter
        clearInterval(counterLine); //clear counterLine
        showResult(); //calling showResult function
    }
}
// getting questions and options from array
function showQuetions(index){
    const que_text = document.querySelector(".que_text");
    //creating a new span and div tag for question and option and passing the value using array index
    let que_tag = '<span>'+ questions[index].numb + ". " + questions[index].question +'</span>';
    let option_tag = '<div class="option"><span>'+ questions[index].options[0] +'</span></div>'
    + '<div class="option"><span>'+ questions[index].options[1] +'</span></div>'
    + '<div class="option"><span>'+ questions[index].options[2] +'</span></div>'
    + '<div class="option"><span>'+ questions[index].options[3] +'</span></div>';
    que_text.innerHTML = que_tag; //adding new span tag inside que_tag
    option_list.innerHTML = option_tag; //adding new div tag inside option_tag
    
    const option = option_list.querySelectorAll(".option");
    // set onclick attribute to all available options
    for(i=0; i < option.length; i++){
        option[i].setAttribute("onclick", "optionSelected(this)");
    }
}
// creating the new div tags which for icons
let tickIconTag = '<div class="icon tick"><i class="fas fa-check"></i></div>';
let crossIconTag = '<div class="icon cross"><i class="fas fa-times"></i></div>';
//if user clicked on option
function optionSelected(answer){
    clearInterval(counter); //clear counter
    clearInterval(counterLine); //clear counterLine
    let userAns = answer.textContent; //getting user selected option
    let correcAns = questions[que_count].answer; //getting correct answer from array
    const allOptions = option_list.children.length; //getting all option items
    
    if(userAns == correcAns){ //if user selected option is equal to array's correct answer
        userScore += 1; //upgrading score value with 1
        answer.classList.add("correct"); //adding green color to correct selected option
        answer.insertAdjacentHTML("beforeend", tickIconTag); //adding tick icon to correct selected option
        console.log("Correct Answer");
        console.log("Your correct answers = " + userScore);
    }else{
        answer.classList.add("incorrect"); //adding red color to correct selected option
        answer.insertAdjacentHTML("beforeend", crossIconTag); //adding cross icon to correct selected option
        console.log("Wrong Answer");
        for(i=0; i < allOptions; i++){
            if(option_list.children[i].textContent == correcAns){ //if there is an option which is matched to an array answer 
                option_list.children[i].setAttribute("class", "option correct"); //adding green color to matched option
                option_list.children[i].insertAdjacentHTML("beforeend", tickIconTag); //adding tick icon to matched option
                console.log("Auto selected correct answer.");
            }
        }
    }
    for(i=0; i < allOptions; i++){
        option_list.children[i].classList.add("disabled"); //once user select an option then disabled all options
    }
    next_btn.classList.add("show"); //show the next button if user selected any option
}
function showResult(){
    info_box.classList.remove("activeInfo"); //hide info box
    quiz_box.classList.remove("activeQuiz"); //hide quiz box
    result_box.classList.add("activeResult"); //show result box
    const scoreText = result_box.querySelector(".score_text");
    if (userScore > 3){ // if user scored more than 3
        //creating a new span tag and passing the user score number and total question number
        let scoreTag = '<span>and congrats! , You got <p>'+ userScore +'</p> out of <p>'+ questions.length +'</p></span>';
        scoreText.innerHTML = scoreTag;  //adding new span tag inside score_Text
    }
    else if(userScore > 1){ // if user scored more than 1
        let scoreTag = '<span>and nice , You got <p>'+ userScore +'</p> out of <p>'+ questions.length +'</p></span>';
        scoreText.innerHTML = scoreTag;
    }
    else{ // if user scored less than 1
        let scoreTag = '<span>and sorry , You got only <p>'+ userScore +'</p> out of <p>'+ questions.length +'</p></span>';
        scoreText.innerHTML = scoreTag;
    }
}
function startTimer(time){
    counter = setInterval(timer, 1000);
    function timer(){
        timeCount.textContent = time; //changing the value of timeCount with time value
        time--; //decrement the time value
        if(time < 9){ //if timer is less than 9
            let addZero = timeCount.textContent; 
            timeCount.textContent = "0" + addZero; //add a 0 before time value
        }
        if(time < 0){ //if timer is less than 0
            clearInterval(counter); //clear counter
            timeText.textContent = "Time Off"; //change the time text to time off
            const allOptions = option_list.children.length; //getting all option items
            let correcAns = questions[que_count].answer; //getting correct answer from array
            for(i=0; i < allOptions; i++){
                if(option_list.children[i].textContent == correcAns){ //if there is an option which is matched to an array answer
                    option_list.children[i].setAttribute("class", "option correct"); //adding green color to matched option
                    option_list.children[i].insertAdjacentHTML("beforeend", tickIconTag); //adding tick icon to matched option
                    console.log("Time Off: Auto selected correct answer.");
                }
            }
            for(i=0; i < allOptions; i++){
                option_list.children[i].classList.add("disabled"); //once user select an option then disabled all options
            }
            next_btn.classList.add("show"); //show the next button if user selected any option
        }
    }
}
function startTimerLine(time){
    counterLine = setInterval(timer, 29);
    function timer(){
        time += 1; //upgrading time value with 1
        time_line.style.width = time + "px"; //increasing width of time_line with px by time value
        if(time > 549){ //if time value is greater than 549
            clearInterval(counterLine); //clear counterLine
        }
    }
}
function queCounter(index){
    //creating a new span tag and passing the question number and total question
    let totalQueCounTag = '<span><p>'+ index +'</p> of <p>'+ questions.length +'</p> Questions</span>';
    bottom_ques_counter.innerHTML = totalQueCounTag;  //adding new span tag inside bottom_ques_counter
}

#html #css #javascript 

How to Create Responsive Pricing Tables using only HTML & CSS

In this blog you’ll learn how to create Responsive Pricing Tables using only HTML & CSS.

To create responsive pricing tables using only HTML & CSS. First, you need to create two Files one HTML File and another one is CSS File

1: First, create an HTML file with the name of index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Pricing Tables | Codequs</title>
    <link rel="stylesheet" href="style.css">
    <script src="https://kit.fontawesome.com/a076d05399.js"></script>
</head>
<body>
  <div class="wrapper">
    <div class="table basic">
      <div class="price-section">
        <div class="price-area">
          <div class="inner-area">
            <span class="text">$</span>
            <span class="price">29</span>
          </div>
        </div>
      </div>
      <div class="package-name"></div>
      <ul class="features">
        <li>
          <span class="list-name">One Selected Template</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">100% Responsive Design</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">Credit Remove Permission</span>
          <span class="icon cross"><i class="fas fa-times"></i></span>
        </li>
        <li>
          <span class="list-name">Lifetime Template Updates</span>
          <span class="icon cross"><i class="fas fa-times"></i></span>
        </li>
      </ul>
      <div class="btn"><button>Purchase</button></div>
    </div>
    <div class="table premium">
      <div class="ribbon"><span>Recommend</span></div>
      <div class="price-section">
        <div class="price-area">
          <div class="inner-area">
            <span class="text">$</span>
            <span class="price">59</span>
          </div>
        </div>
      </div>
      <div class="package-name"></div>
      <ul class="features">
        <li>
          <span class="list-name">Five Existing Templates</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">100% Responsive Design</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">Credit Remove Permission</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">Lifetime Template Updates</span>
          <span class="icon cross"><i class="fas fa-times"></i></span>
        </li>
      </ul>
      <div class="btn"><button>Purchase</button></div>
    </div>
    <div class="table ultimate">
      <div class="price-section">
        <div class="price-area">
          <div class="inner-area">
            <span class="text">$</span>
            <span class="price">99</span>
          </div>
        </div>
      </div>
      <div class="package-name"></div>
      <ul class="features">
        <li>
          <span class="list-name">All Existing Templates</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">100% Responsive Design</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">Credit Remove Permission</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
        <li>
          <span class="list-name">Lifetime Template Updates</span>
          <span class="icon check"><i class="fas fa-check"></i></span>
        </li>
      </ul>
      <div class="btn"><button>Purchase</button></div>
    </div>
  </div>
</body>
</html>

2: Second, create a CSS file with the name of style.css

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 20px;
  background: #647df9;
}
.wrapper{
  max-width: 1090px;
  width: 100%;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.wrapper .table{
  background: #fff;
  width: calc(33% - 20px);
  padding: 30px 30px;
  position: relative;
  box-shadow: 0 5px 10px rgba(0,0,0,0.1);
}
.table .price-section{
  display: flex;
  justify-content: center;
}
.table .price-area{
  height: 120px;
  width: 120px;
  border-radius: 50%;
  padding: 2px;
}
.price-area .inner-area{
  height: 100%;
  width: 100%;
  border-radius: 50%;
  border: 3px solid #fff;
  line-height: 117px;
  text-align: center;
  color: #fff;
  position: relative;
}
.price-area .inner-area .text{
  font-size: 25px;
  font-weight: 400;
  position: absolute;
  top: -10px;
  left: 17px;
}
.price-area .inner-area .price{
  font-size: 45px;
  font-weight: 500;
  margin-left: 16px;
}
.table .package-name{
  width: 100%;
  height: 2px;
  margin: 35px 0;
  position: relative;
}
.table .package-name::before{
  position: absolute;
  top: 50%;
  left: 50%;
  font-size: 25px;
  font-weight: 500;
  background: #fff;
  padding: 0 15px;
  transform: translate(-50%, -50%);
}
.table .features li{
  margin-bottom: 15px;
  list-style: none;
  display: flex;
  justify-content: space-between;
}
.features li .list-name{
  font-size: 17px;
  font-weight: 400;
}
.features li .icon{
  font-size: 15px;
}
.features li .icon.check{
  color: #2db94d;
}
.features li .icon.cross{
  color: #cd3241;
}
.table .btn{
  width: 100%;
  display: flex;
  margin-top: 35px;
  justify-content: center;
}
.table .btn button{
  width: 80%;
  height: 50px;
  color: #fff;
  font-size: 20px;
  font-weight: 500;
  border: none;
  outline: none;
  border-radius: 25px;
  cursor: pointer;
  transition: all 0.3s ease;
}
.table .btn button:hover{
  border-radius: 5px;
}
.basic .features li::selection{
  background: #ffd861;
}
.basic ::selection,
.basic .price-area,
.basic .inner-area{
  background: #ffd861;
}
.basic .btn button{
  border: 2px solid #ffd861;
  background: #fff;
  color: #ffd861;
}
.basic .btn button:hover{
  background: #ffd861;
  color: #fff;
}
.premium ::selection,
.premium .price-area,
.premium .inner-area,
.premium .btn button{
  background: #a26bfa;
}
.premium .btn button:hover{
  background: #833af8;
}
.ultimate ::selection,
.ultimate .price-area,
.ultimate .inner-area{
  background: #43ef8b;
}
.ultimate .btn button{
  border: 2px solid #43ef8b;
  color: #43ef8b;
  background: #fff;
}
.ultimate .btn button:hover{
  background: #43ef8b;
  color: #fff;
}
.basic .package-name{
  background: #ffecb3;
}
.premium .package-name{
  background: #d0b3ff;
}
.ultimate .package-name{
  background: #baf8d4;
}
.basic .package-name::before{
  content: "Basic";
}
.premium .package-name::before{
  content: "Premium";
  font-size: 24px;
}
.ultimate .package-name::before{
  content: "Ultimate";
  font-size: 24px;
}
@media (max-width: 1020px) {
  .wrapper .table{
    width: calc(50% - 20px);
    margin-bottom: 40px;
  }
}
@media (max-width: 698px) {
  .wrapper .table{
    width: 100%;
  }
}
::selection{
  color: #fff;
}
.table .ribbon{
  width: 150px;
  height: 150px;
  position: absolute;
  top: -10px;
  left: -10px;
  overflow: hidden;
}
.table .ribbon::before,
.table .ribbon::after{
  position: absolute;
  content: "";
  z-index: -1;
  display: block;
  border: 7px solid #4606ac;
  border-top-color: transparent;
  border-left-color: transparent;
}
.table .ribbon::before{
  top: 0px;
  right: 15px;
}
.table .ribbon::after{
  bottom: 15px;
  left: 0px;
}
.table .ribbon span{
  position: absolute;
  top: 30px;
  right: 0;
  transform: rotate(-45deg);
  width: 200px;
  background: #a26bfa;
  padding: 10px 0;
  color: #fff;
  text-align: center;
  font-size: 17px;
  text-transform: uppercase;
  box-shadow: 0 5px 10px rgba(0,0,0,0.12);
}

Now you’ve successfully created Responsive Pricing Tables using only HTML & CSS.

How to Create a Landing Page using HTML, CSS & JavaScript

Web Development Project – How to Make a Landing Page with HTML, CSS, and JavaScript

Having a good landing page for your website is important. It can help drive customers to your site where they'll find your products and services and hopefully take action.

In this text-based tutorial, I’m going to take you through how to make a landing page for a boxing TV channel with plain HTML, CSS, and JavaScript.

The name of our fictional TV channel is JabTV, and the purpose of making the landing page is to collect emails.

By the end of this tutorial, you will be able to make:

  • a responsive hamburger menu
  • a dark and light theme switcher
  • a lightbox image gallery
  • a scroll-to-top button
  • and most importantly, a responsive web page

It doesn’t end with those benefits. I believe that as a beginner, you will be able to level up your CSS too after completing this tutorial.

To follow along with me, grab the starter files from this GitHub repo
Check out the live demo too so you can get familiar with what we are building.

Table of Contents

  • The Project Folder Structure
  • The Basic HTML Boilerplate
  • How to Make the Navbar
  • How to Style the Navbar
  • How to Make the Hero Section
  • How to Style the Hero Section
  • How to Make the About Section
  • How to Make the Lightbox Image Gallery
  • How to Style the Lightbox Image Gallery
  • How to Make the Stakeholders Section
  • How to Style the Stakeholders Section
  • How to Make the Email Subscription Section
  • How to Style the Email Subscription Section
  • How to Make the Footer
  • How to Make the Scroll-to-top Button
  • How to Make the Dark and Light Theme Switcher
  • How to Style the Dark and Light Theme Switcher
  • How to Make the Landing Page Responsive
  • How to Make a Hamburger Menu for the Landing Page
  • Conclusion

The Project Folder Structure

The folder structure follows the convention that many front end developers use.

The HTML and readme files and a screenshot for the readme are in the root. The CSS files, JavaScript files, icons, and images go in their respective subfolders inside the assets folder.

ss-1

The Basic HTML Boilerplate

The basic HTML boilerplate looks like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- Web page CSS -->
    <link rel="stylesheet" href="assets/css/styles.css" />

    <!-- Simple lightbox CSS -->
    <link rel="stylesheet" href="assets/css/simple-lightbox.min.css" />

    <!-- Favicons -->
    <link
      rel="apple-touch-icon"
      sizes="180x180"
      href="assets/icons/apple-touch-icon.png"
    />
    <link
      rel="icon"
      type="image/png"
      sizes="32x32"
      href="assets/icons/favicon-32x32.png"
    />
    <link
      rel="icon"
      type="image/png"
      sizes="16x16"
      href="assets/icons/favicon-16x16.png"
    />

    <title>JabTV Landing Page</title>
  </head>
  <body>
    <!-- Navbar -->

    <!-- Dark/light theme switcher -->

    <!-- Bars -->

    <!-- Hero section -->

    <!-- About section -->

    <!-- Lightbox image gallery -->

    <!-- Jab TV Stakeholders -->

    <!-- Email subscription -->

    <!-- Social icons -->

    <!-- Scroll to top button -->

    <!-- Web page script -->
    <script src="assets/js/app.js"></script>

    <!-- Ion icons CDN -->
    <script
      type="module"
      src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.esm.js"
    ></script>

    <!-- Simple lightbox -->
    <script src="assets/js/simple-lightbox.min.js"></script>
    <script>
      // Simple lightbox initializer
    </script>
  </body>
</html>

We will be coding the landing page section by section so it doesn’t get too complicated to understand.

How to Make the Navbar

The navbar will have a logo to the left and nav menu items to the right. Later, we'll place the dark and light theme switcher between the logo and nav items, but let’s focus on the logo and menu items first.

For the logo, I won’t be using an image but a combination of text and emoji placed inside a span tag so I can style them differently.

The HTML for the logo looks like this:

<nav>
      <a href="#" class="logo">
        <h1>
          <span class="jab">Jab</span><span class="tv">TV</span
          ><span class="fist">&#x1F44A;</span>
        </h1>
      </a>
</nav>

It’s a combination of the words “Jab” and “TV”, with a punch emoji.

The nav menu items are generic links placed in an unordered list tag, as shown in the snippet below:

<ul>
        <li class="nav-item">
          <a href="#about" class="nav-link" id="nav-link">About</a>
        </li>
        <li class="nav-item">
          <a href="#stars" class="nav-link" id="nav-link">Boxing Stars</a>
        </li>
        <li class="nav-item">
          <a href="#stakeholders" class="nav-link" id="nav-link"
            >stakeholders</a
          >
        </li>
        <li class="nav-item">
          <a href="#sub" class="nav-link" id="nav-link">Subscribe</a>
        </li>
</ul>

In addition, we need some bars for the mobile menu. The bars will be hidden on the desktop version and visible on mobile phones.

For this, I will be using bars made with raw HTML and CSS, not icons. The bars will be span tags placed in a container div with a class of hamburger.

<div class="hamburger" id="hamburger">
    <span class="bar"></span>
    <span class="bar"></span>
    <span class="bar"></span>
</div>

The nav menu now looks like this in the browser:
ss-2

How to Style the Navbar

The navbar looks pretty ugly at this point, so we need to style it. We need to style the logo to make it look like one, and we'll use Flexbox to place the logo and menu items side by side.

For the whole web page, I will be using the Roboto font. I also have some CSS variables declared and some less complicated resets.

@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,900;1,700&display=swap");

/* CSS Variables */
:root {
  --normal-font: 400;
  --bold-font: 600;
  --bolder-font: 900;
  --primary-color: #0652dd;
  --secondary-color: #ea2027;
  --line-height: 1.7rem;
  --transition: 0.4s ease-in;
}

/* Smooth scroll effect */
html {
  scroll-behavior: smooth;
}

/* Resets */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  transition: var(--transition);
}

 body {
  font-family: "Roboto", sans-serf;
}

ul li {
  list-style-type: none;
}

a {
  text-decoration: none;
  color: var(--primary-color);
}

a:hover {
  color: var(--secondary-color);
} 

In the CSS code snippet above, I’m removing the default margin and padding assigned to all elements by browsers and setting the box-sizing to border-box. This way the padding and margin set will be more intentional.

I also set a transition (declared in the variables) so you will be able to see every transition on the website.

All links will be blue in appearance and red on hover – correlating to the primary and secondary colors.

To style the logo, I will make the first <span> red, the second <span> blue, and the .fist red. Both red and blue colors have been set as the secondary color and primary color respectively in the CSS variables.

The red and blue colors are commonly used in amateur boxing and other combat sports, which is why I chose them for the website.

.fist {
  color: var(--secondary-color);
}

.jab {
  color: var(--primary-color);
}

.tv {
  color: var(--secondary-color);
}

So far, the navbar looks like this:
ss-3

To place the logo and menu items side by side, I will be using Flexbox. I will also hide the bars because we only need them on mobile devices.

nav {
  background: #fff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 1.5rem;
  box-shadow: 2px 3px 2px #f1f1f1;
}

I applied a box shadow to make sure the user knows where the navbar terminates.

I’m also going to make the navbar sticky, so it always stays at the top whenever the user scrolls down. This helps create a good user experience.

I will do it with 4 lines of CSS:

 position: sticky;
  top: 0;
  left: 0;
  z-index: 1;

To hide the bars, I’m going to target the .hambuger class and give it a display of none:

.hamburger {
  display: none;
}

The navbar looks a lot better:
ss-4-1

But the logo should be bigger. We also need to make sure the menu items are side by side and not on top of one another, so Flexbox will be instrumental here again.

.logo {
  font-size: 2rem;
  font-weight: 500;
}

ul {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.nav-item {
  margin-left: 2rem;
}

.nav-link {
  font-weight: var(--bold-font);
}

Take a look at the navbar now:
ss-5

It doesn’t get better than that!

And take note that the logo is not an image. This means you can always update it with CSS.

How to Make the Hero Section

The hero section is going to contain a short description of JabTV, call to action (CTA) buttons, and an old-school TV made with CSS art. We'll make the TV with the iframe tag so a video can be displayed inside it.

The video we'll place in the iframe is of boxing great Mohammed Ali.

In short, this is what we are working towards:
ss-6

The HTML for the hero section is in the code snippet below:

    <section class="hero">
      <div class="intro-text">
        <h1>
          <span class="hear"> You can Hear the Jabs </span> <br />
          <span class="connecting"> Connecting</span>
        </h1>
        <p>
          An online streaming platform for boxing matches <br />
          We also dedicate some special time to throwbacks cuz old is gold
        </p>
        <a class="btn red" href="#">Learn More</a>
        <a class="btn blue" href="#">Subscribe</a>
      </div>
      <div class="i-frame">
        <iframe
          width="560"
          height="315"
          src="https://www.youtube.com/embed/sUmM_PFpsvQ"
          title="YouTube video player"
          frameborder="10"
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
        ></iframe>
        <div class="stand-1"></div>
        <div class="stand-2"></div>
      </div>
    </section>

With the HTML above, this is what we have in the browser:
ss-7-1

How to Style the Hero Section

To align the text and TV side by side, we need Flexbox.

display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.9rem;
  max-width: 1100px;
  margin: 2rem auto -6rem;
}

Apart from aligning things with Flexbox, I also gave the section a maximum width of 1100px so the user won't have to look all the way to the extreme end to see the content of the section – this is good for user experience.

I applied a margin of 2rem on top, auto on the left and right, and -6rem on the bottom to center everything in the section.

So far, we have this in the browser:
ss-8

To style the h1 texts of the hero section, I put them in their respective span tags, so I can style them differently.

Therefore, I will target the texts with the class attributes of the span tags:

.intro-text h1 {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.intro-text h3 {
  margin-bottom: 0.5rem;
}

.hero p {
  line-height: var(--line-height);
}

.hear {
  color: var(--primary-color);
}

.connecting {
  color: var(--secondary-color);
}

Remember there are 2 buttons in the section, so I have a basic style defined for them:

.btn {
  margin-top: 1rem;
  display: inline-block;
  padding: 0.8rem 0.6rem;
  border: none;
  font-size: 1.4rem;
  border-radius: 5px;
  color: #fff;
}

.red {
  background-color: var(--secondary-color);
  margin-right: 1.5rem;
}

.red:hover {
  background-color: #f1262d;
  color: #fff;
}

.blue {
  background-color: var(--primary-color);
}

.blue:hover {
  background-color: #095cf7;
  color: #fff;
}

The section is taking shape:
ss-9

Next, we need to make the iframe look like a TV. The border property will help us get that done.

From the HTML, remember I have 2 div tags with the classes of stand-1 and stand-2. I’m going to make the stands for the old school TV with the 2 div tags by using the transform property – which is instrumental in rotating or skewing an element.

iframe {
  max-width: 30rem;
  border-top: 40px groove var(--primary-color);
  border-bottom: 40px groove var(--primary-color);
  border-right: 28px solid var(--secondary-color);
  border-left: 28px solid var(--secondary-color);
}

.stand-1 {
  height: 90px;
  width: 6px;
  background-color: var(--primary-color);
  transform: rotate(40deg);
  position: relative;
  top: -16px;
  left: 200px;
}
.stand-2 {
  height: 90px;
  width: 6px;
  background-color: var(--secondary-color);
  transform: rotate(-40deg);
  position: relative;
  top: -105px;
  left: 255px;
}

To be able to move the stands around, I used the position property and set it to relative, which subsequently helped me assign left and top properties to the stands.

The hero section has now taken full shape:
ss-10-1

How to Make the About Section

The about section will do what the name implies – it will detail what JabTV is about as briefly as possible. The section will contain text and a background image.

The HTML for this section is not complicated:

 <section class="about" id="about">
      <h3>Watch the Jabs</h3>
      <p>
        Our primary objective is to bring live boxing matches to fans all around
        the world
      </p>

      <h3>Its not About the Fights Alone!</h3>
      <p>
        We also air documentaries specially made for the greats, lifestyle of
        boxers, news, and more.
      </p>
</section>

If you’re wondering why there’s no img tag, it’s because I planned to bring in the background image with the CSS background property.

The background property is a shorthand for:

  • background-color
  • background-image
  • background-position
  • background-cover
  • background-repeat
  • background-origin
  • background-clip
  • and background-attachment

Only what you specify will be applied, so you can always skip any of the properties.

Apart from the background property, I will also use Flexbox to align the text from the HTML so they can look nice on the background image.

This is how I used the position property in combination with Flexbox:

.about {
  position: relative;
  background: url("../images/jab-transformed.png") no-repeat top center/cover;
  height: 600px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 1.5rem;
  margin: 2rem 0;
}

And this is how the section looks in the browser so far:
ss-11

To make the texts look readable and nicer, I employed some more CSS:

.about h3 {
  font-size: 3em;
  margin-bottom: -20px;
}

.about p {
  font-size: 1.5em;
}

.about h3 {
  text-shadow: 2px 2px 2px #333;
}

.about p {
  text-shadow: 2px 2px 2px #333;
  font-size: 1.8rem;
}

Take note that I applied text shadow to the texts since they are displayed on an image. You should do this in every project for better accessibility.

The About section looks a lot nicer now:
ss-12

How to Make the Lightbox Image Gallery

For the lightbox image gallery, I will not be doing it from scratch – otherwise, this tutorial would become unbearably long. I will be using a plugin called simple lightbox, and CSS grid for the alignment of the images.

To use the simple lightbox plugin, you have to download it from their website. All we need is the minified CSS and JavaScript file.

When you extract the downloaded zip file, copy and paste the minified CSS and JavaScript file to the js and css subfolders inside assets, and link them appropriately, as I have done in the starter HTML.

To make the lightbox work, you have to wrap an anchor tag (<a>) around the image in an <img> tag.

The href of the anchor tag must also correlate with the image source, and they all must go inside a containing div tag which you'll need to assign a class attribute to.

This class attribute will be used to initialize the gallery with JavaScript. Don’t worry, the JavaScript will not be complicated. The gallery will feature boxing stars who I think are among the greatest.

The HTML for the simple lightbox image gallery is in the code snippet below:

<section class="stars" id="stars">
      <div class="stars-gallery">
        <a href="assets/images/boda--femi.jpg" class="big">
          <img
            src="assets/images/boda--femi.jpg"
            alt="Anthony Joshua"
            title="AJ"
          />
        </a>

        <a href="assets/images/tyson-fury.jpg" class="big">
          <img
            src="assets/images/tyson-fury.jpg"
            alt="Tyson Fury"
            title="Gypsy King"
          />
        </a>

        <a href="assets/images/iron-mike.webp.jpg" class="big">
          <img
            src="assets/images/iron-mike.webp.jpg"
            alt="Iron Mike"
            title="Iron Mike"
          />
        </a>

        <a href="assets/images/ali.jpg" class="big">
          <img
            src="assets/images/ali.jpg"
            alt="Mohammed Ali"
            title="The Greatest"
          />
        </a>

        <a href="assets/images/wilder.jpg" class="big"
          ><img
            src="assets/images/wilder.jpg"
            alt="Deontay Wilder"
            title="Bronze Bomber"
          />
        </a>

        <a href="assets/images/big-george.jpg" class="big">
          <img
            src="assets/images/big-george.jpg"
            alt="George Foreman"
            title="Big George Foreman"
          />
        </a>
      </div>
</section>

To make the gallery work and scroll smoothly while viewing the images, you have to initialize it with one line of JavaScript:

<script>
     var lightbox = new SimpleLightbox(".stars-gallery a");
</script>

Our lightbox image gallery is now working:
gif1

How to Style the Lightbox Image Gallery

The images are badly aligned, so we need to arrange them with CSS Grid:

.stars-gallery {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}

In the CSS code snippet above, I targeted the div with a class of stars-gallery and gave it a display of grid, so we can use other properties of CSS on the elements inside the div.

I defined the column I need with grid-template-columns: repeat(5, 1fr);, which would confine the images into 5 columns.

So far, this is what the gallery looks like:
gif2

More still need to be done, because there is a white space and one of the images is not visible anymore.

I will give all the images a height and width of 100%, so they can all be visible:

.stars-gallery img,
.stars-gallery a {
  width: 100%;
  height: 100%;
}

ss-13

Next, I will target the first image and define a grid row and column for it:

.stars-gallery a:first-child {
  grid-row: 1/3;
  grid-column: 1/3;
}

With the defined grid row and column, the first image will occupy the first 2 rows horizontally, and the first 2 columns vertically.

I will also target the second image and define a grid column for it:

.stars-gallery a:nth-child(2) {
  grid-column: 3/5;
}

Our image gallery is now nicely arranged and working fine:
gif3

How to Make the Stakeholders Section

The stakeholders section contains those responsible for running JabTV.

The HTML for this section is in the snippet below:

<section class="people" id="stakeholders">
      <div class="stakeholders">
        <div class="persons">
          <div class="person-1">
            <img src="assets/images/john.jpg" alt="John Doe" />
            <p class="name">John Doe</p>
            <p class="role">Founder</p>
          </div>
          <div class="person-2">
            <img src="assets/images/jane.jpg" alt="Jane Doe" />
            <p class="name">Jane Doe</p>
            <p class="role">MD</p>
          </div>
          <div class="person-3">
            <img src="assets/images/jnr.jpg" alt="John Doe Jnr" />
            <p class="name">John Doe JNR</p>
            <p class="role">Head Analyst</p>
          </div>
        </div>
      </div>
</section>

This is what the section looks like:
ss-14

But that’s not how we want it, so we have some styling to do.

How to Style the Stakeholders Section

I will be using CSS grid to layout the images, names, and roles of the stakeholders. You can use Flexbox for this if you want. But before that, I’m going to do a little tweak for the section:

 .people {
  margin-top: 2rem;
  padding: 1rem 0;
}

.stakeholders {
  margin: 2rem auto;
  max-width: 1100px;
}

.stakeholders img {
  border-radius: 0.6rem;
}

In the code snippet above, I pushed the section down a little with a margin-top of 2rem. I targeted the .people class to do this.

The next thing I did was target the .stakeholders class, and I assigned it a margin of 2rem on the top and bottom. I also centered it on the left and right with auto.

Targeting the .stakeholders class again, I also gave the section a maximum width of 1100px, so spaces are created on the left and right. This makes sure that the user doesn’t look to the extreme left and right before seeing things.

This makes things look a little better:
ss-15-1

To finally layout the images and text with CSS grid, this is what I did:

.persons {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  place-items: center;
  gap: 1rem;
}

Since there are 3 images in a div:

  • I defined 3 columns for the section
  • aligned everything to the center horizontally and vertically with place-items
  • added space of 1rem within the div tags with the gap property

Everything now looks good apart from the text:
ss-16

To make the text look better, I’m going to target it with the .name and .role classes and align it to the center, and then assign it a color and font where necessary:

.name {
  color: var(--primary-color);
  text-align: center;
}

.role {
  color: var(--secondary-color);
  text-align: center;
  font-size: 0.8rem;
}

The section now looks good enough:
ss-17

How to Make the Email Subscription Section

The email subscription section is going to be as short as possible. I will not be doing any integration for collecting emails here.

For this purpose, if you want to simply collect emails, you can use formspree. It’s better to use a service like Mailchimp or Convertkit, though, so you can do something with the emails you've collected.

The HTML for this section is just 12 lines:

<section class="sub" id="sub">
      <h3>Subscribe to our newsletter for updates</h3>
      <form action="#">
        <input
          type="email"
          name="email"
          id="email-sub"
          class="email-sub"
          required
        />
        <input
          type="submit"
          value="Subscribe"
          id="submit-btn"
          class="submit-btn"
        />
      </form>
</section>

As you can see, I have an input for email and a submit button inside a form.
The section doesn’t look too bad in the browser:
ss-18

How to Style the Email Subscription Section

We need to align the h3 and form to the center, and make the subscribe button look good.

This is how I aligned the h3 and form to the center:

.sub {
  margin-top: 2rem;
}

.sub h3 {
  text-align: center;
}

form {
  text-align: center;
  margin: 0.4rem 2rem;
}

Notice I also pushed the section to the bottom a little with a margin of 2rem.

To push the form away from the h3, I gave it a margin of 0.4rem at the top and bottom, and 2rem at the left and right.

The form now looks a lot better:
ss-19

The next thing we should do is make the input area and subscribe button look better. I attached a class of .email-sub to the input area, so I’m going to target it with the class and apply some styling:

.email-sub {
  padding: 0.2rem;
  border: 1px solid var(--primary-color);
  border-radius: 4px;
}

.email-sub:focus {
  border: 1px solid var(--secondary-color);
  outline: none;
}

Here's what's happening to the input area with the CSS above:

  • I gave the input a padding of 0.2rem for better spacing
  • I gave it (the input) a blue solid border of 1px
  • I made the corners of the input rounded with a border-radius of 4px
  • when focused, that is when you’re trying to type in the input, I changed the border color to the website’s secondary color
  • lastly, I set the outline to none to remove the ugly outline that shows while typing in the input areas.

I made the subscribe button look better with the CSS below:

.submit-btn {
  background-color: var(--primary-color);
  color: #fff;
  padding: 0.3rem;
  margin: 0 0.5rem;
  border: none;
  border-radius: 2px;
  cursor: pointer;
}

.submit-btn:hover {
  background-color: #095cf7;
}

The subscription section now looks really cool:
ss-20

I’m also going to include some social icons in the section.
For the icons, I will be using ionic icons.

The icons will be wrapped in an anchor tag, so they can inherit the styles set for links in the CSS resets.

<section class="social">
      <h3>Connect with us on Social Media</h3>
      <div class="socicons">
        <a href="#"> <ion-icon name="logo-twitter"></ion-icon> </a>
        <a href="#"> <ion-icon name="logo-instagram"></ion-icon> </a>
        <a href="#"> <ion-icon name="logo-facebook"></ion-icon> </a>
      </div>
</section>

The CSS for the social icons is not complicated:

.social {
  text-align: center;
  margin: 2rem;
}

.socicons {
  font-size: 1.3rem;
}

This is how the email subscription section finally looks:
ss-21

To learn more about Ionic icons, check the readme attached to the project on GitHub.

How to Make the Footer

The HTML for the footer is a one-liner:

<footer>&copy;2020. All Rights Reserved</footer>

If you are wondering what &copy; is, that’s the character entity for the © you always see in website footers.

The CSS is all done in 6 lines:

footer {
  border-top: 1px solid #f1f1f1;
  box-shadow: 0px -2px 3px #f1f1f1;
  text-align: center;
  padding: 2rem;
}

I applied a border-top and box-shadow to the footer so the upper part of it can correlate with the navbar.

ss-22

How to Make the Scroll-to-top Button

For a better user experience, let’s implement a scroll-to-top button. When clicked, this button will take the user to the top of the page from wherever they are.

The HTML for the scroll-to-top button is in the code snippet below:

<i class="scroll-up" id="scroll-up"
     ><img
       src="assets/icons/icons8-upward-arrow.png"
       class="socicon up-arrow"
       alt="up-arrow"
/></i>

We'll use the class attributes to style the button, and the ids to select it in our JavaScript file. That’s how we will do things in the CSS and JavaScript.

To make the button visible everywhere and look good, I’m going to give it a fixed position and increase the width and height. I will also give it a cursor of pointer, so the user knows what is happening when they hover their cursor on it.

.scroll-up {
  position: fixed;
  right: 0.5%;
  bottom: 3%;
  cursor: pointer;
}

.up-arrow {
  width: 3rem;
  height: 3rem;
}

ss-23

To finally implement the scroll-to-top functionality, we will write 7 lines of JavaScript:

const scrollUp = document.querySelector("#scroll-up");

scrollUp.addEventListener("click", () => {
  window.scrollTo({
    top: 0,
    left: 0,
    behavior: "smooth",
  });
});

What is the script doing?

In the first line, I selected the button by assigning it to a variable called scrollUp.

I used the querySelector() method for this because it is reportedly faster. You can use getElementById too.

To get the user’s click action on the button, I used an important feature of the DOM (Document Object Model) called eventListener.

In the eventListener() function, I brought in a window object method called scrollTo, which helps move to anywhere on the web page.

To tell the scrollTo method where to scroll to, you have to assign it a property of either top and left, or top and bottom as the case may be. So I assigned it a top and left of 0.

The last thing I did was set the behavior property to a string of “smooth”, so things animate smoothly when the button is clicked.

Our scroll-to-top button is now working perfectly:
gif4

We now have a complete website! But let’s take things a little further by adding a dark and light theme switcher, since a lot of people now enjoy using websites in dark mode.

How to Make the Dark and Light Theme Switcher

To make the dark theme switcher accessible anywhere on the landing page, I’m going to put it in our sticky navbar.

I will be using:

  • a div with the class of theme-switch to house everything
  • an input type of checkbox to switch between dark and light mode
  • a label to put in the 2 icons for moon (dark mode) and sun (light mode)
  • a div with a class of switcher inside the label to create a ball-like shape. This shape would cover one icon when the user switches to either light or dark mode

This is how I converted the above points to HTML code:

<div class="theme-switch">
    <input type="checkbox" class="checkbox" id="checkbox" />
    <label for="checkbox" class="label">
       <ion-icon name="partly-sunny-outline" class="sun"></ion-icon>
       <ion-icon name="moon-outline" class="moon"></ion-icon>
       <div class="switcher"></div>
    </label>
</div>

And this is how it looks in the browser:
ss-24_LI

How to Style the Dark and Light Theme Switcher

The first thing I’m going to do is make the checkbox invisible and position it absolute.

We need to do this because what we need is the functionality of a checkbox to switch between light and dark mode – but we don’t need to make it visible to the user.

.checkbox {
  opacity: 0;
  position: absolute;
}

Next, I’m going to position the label relative, center everything in it with Flexbox, and give it a dark background. With this and some other minor stylings, the dark theme switcher will be more visible.

.label {
  width: 50px;
  height: 29px;
  background-color: #111;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 30px;
  padding: 6px;
  position: relative;
}

ss-25_LI

All you see now is a dark background. Don’t worry. Everything will become visible again.

Remember the div with a class of switcher? Let’s make it white and round to truly look like a ball. We will also position it absolute because its inside the label which has been positioned relative.

.switcher {
  background-color: #fff;
  position: absolute;
  top: 5px;
  left: 2px;
  height: 20px;
  width: 20px;
  border-radius: 50%;
}

Defining width, height, and a border-radius of 50% is how you make anything round in CSS.ss-27

Our dark theme switcher is taking shape, but let’s make the icons visible by giving them the appropriate colors of reddish for sun and yellowish for moon.

.moon {
  color: #ffa502;
}

.sun {
  color: #ff4757;
}

Finally, to be able to move the ball left and right, we need to use the :checked pseudo-class on our checkbox, and target the ball with a class of switcher, then use the transform property to move it by setting a figure in pixels:

.checkbox:checked + .label .switcher {
  transform: translateX(24px);
}

Our ball is now moving and the icons are correctly showing:
gif5

What we need to do now is use JavaScript to toggle between the light and dark mode and set the colors for dark mode.

You can find the color set for our dark theme in the snippet below:

body.dark {
  background-color: #1e272e;
}

body.dark .bar {
  background-color: #fff;
}

body.dark p {
  color: #fff;
}

body.dark h3 {
  color: #fff;
}

body.dark nav {
  background-color: #1e272e;
  box-shadow: 2px 3px 2px #111010;
}

body.dark ul {
  background-color: #1e272e;
}

body.dark .name {
  color: var(--primary-color);
}

body.dark .role {
  color: var(--secondary-color);
}

body.dark footer {
  color: #fff;
  border-top: 1px solid #111010;
  box-shadow: 0px -2px 3px #111010;
}

And here’s how I used JavaScript to toggle the body.dark class by using change event on the checkbox and the toggle() method of DOM:

const checkbox = document.querySelector("#checkbox");

checkbox.addEventListener("change", () => {
  // Toggle website theme
  document.body.classList.toggle("dark");
});

Notice that I selected the checkbox with an id of #checkbox and assigned it to a checkbox variable. Try to always use ids for JavaScript and classes for CSS, so you don’t get confused.

Users can nohw toggle light and dark modes on our landing page:
gif6

How to Make the Landing Page Responsive

The landing page is not responsive yet, so we should fix that.

To make the landing page responsive, we need to make a hamburger menu for smaller devices, inside a media query. We will also use Flexbox and Grid once again to make the sections stack on top of one another.

How to Make a Hamburger Menu for the Landing Page

For the hamburger menu, the first thing I’m going to do is make the bars visible on a device with a screen width less than 768 pixels.

I will also set a cursor of pointer for the bars, so the user knows they can click when they hover their mouse on it.

@media screen and (max-width: 768px) {
  .hamburger {
    display: block;
    cursor: pointer;
  }

Next, I will change the flex direction of the nav menu items to column by targeting the unordered list they are contained in, so they go on top of one another.

I will also give the list a white background, align every item in it to the center, and make the list items fixed with the left property set to 100%, so it will be taken out of the viewport (invisible).

ul {
    background-color: #fff;
    flex-direction: column;
    position: fixed;
    left: 100%;
    top: 5rem;
    width: 100%;
    text-align: center;
  }

So far, this is what we have in the browser:
ss-27-1

To make the nav items visible, I’m going to attach a class attribute of active to the unordered list containing them and set left to 0. This class will be toggled with JavaScript when the user clicks the bars.

ul.active {
    left: 0;
}

The nav items have become poorly spaced:
ss-28

To make sure the nav menu items are well-spaced, I’m going to target them with the .nav-item class and give them some margins:

.nav-item {
    margin: 2rem 0;
  }

The CSS snippet above gives each nav menu item a margin of 2rem on the top and bottom, and 0 on the left and right, so they look like this:
ss-29

There’s one more thing to do with the bars – we need to make sure they change to an X shape when they are clicked, and back to the bars when clicked again.

To do this, we will attach a class of active to the hamburger menu, and then rotate the bars. Remember that this active class will be toggled by JavaScript.

.hamburger.active .bar:nth-child(2) {
    opacity: 0;
  }

  .hamburger.active .bar:nth-child(1) {
    transform: translateY(10px) rotate(45deg);
  }

  .hamburger.active .bar:nth-child(3) {
    transform: translateY(-10px) rotate(-45deg);
  } 

To do the toggling, we need some JavaScript:

const hamburger = document.querySelector("#hamburger");
const navMenu = document.querySelector("ul");

function openMenu() {
  hamburger.classList.toggle("active");
  navMenu.classList.toggle("active");
}

Here's what I did in the JavaScript:

  • I selected the bars with the id of hamburger, and the unordered list with the element (ul)
  • I wrote a function named openMenu to get the classlists of the hamburger menu and unordered list, then used the toggle() method to bring in the active class.

Our nav menu items are now being toggled back and forth with the bars changing shape as needed:
gif8gif

But there’s a problem. The menu items are not hidden any time one of them is clicked. We need to make this happen for a better user experience.

To do this, we need some JavaScript again. We will:

  • select all the nav items with querySelectorAll() by targeting their ids
  • listen for a click event on each of the nav menu items with the forEach() array method
  • write a function to remove the .active class – which will eventually return the nav menu to its original state.
const navLink = document.querySelectorAll("#nav-link");

navLink.forEach((n) => n.addEventListener("click", closeMenu));
function closeMenu() {
  hamburger.classList.remove("active");
  navMenu.classList.remove("active");
}

Everything now works fine with our mobile menu:
gif9

If you noticed, other parts of the website are not looking good on mobile devices. There’s even an annoying horizontal scrollbar. This is not 1998 but 2022!
gif10

Adding the following styles to the media query will fix it:

 .logo {
    font-size: 1.5rem;
  }
 
 .hero {
    flex-direction: column;
    max-width: 500px;
  }

  .intro-text h1 {
    font-size: 2.3rem;
  }

  .btn {
    padding: 0.5rem;
    font-size: 1.2rem;
  }

  iframe {
    max-width: 26rem;
  }

  .stand-1 {
    left: 170px;
  }
  .stand-2 {
    left: 225px;
  }

  .about {
    text-align: center;
  }

  .persons {
    grid-template-columns: repeat(1, 1fr);
  } 
}

With the CSS above, I reduced sizes, changed the direction to column where necessary so the sections stack on top of one another, and made the TV stands aligned properly.
gif11

Looking at the landing page on smaller phones, we really can do better:
gif12

To make the landing page responsive on smaller phones, I will integrate few changes on mobile devices of screen width 420px and below:

@media screen and (max-width: 420px) {
  .hero {
    max-width: 330px;
  }

  .intro-text h1 {
    font-size: 2rem;
  }

  iframe {
    max-width: 330px;
  }

  .stand-1 {
    left: 140px;
  }
  .stand-2 {
    left: 195px;
  }
}

We now have a fully responsive landing page:
gif13.

Grab the finished copy of the landing page code from this Github repo.

Conclusion

In this detailed tutorial, you have learned how to make a:

  • fully responsive website
  • dark theme switcher
  • hamburger menu
  • lightbox image gallery
  • scroll-to-top button.

These are functionalities you can always integrate into a new or existing project, so feel free to always come back to this article any time you need it.

If you find this text-based tutorial helpful, share it by tweeting a thanks or pasting the link on your social media platforms.

Thank you for reading!

Original article source at https://www.freecodecamp.org

#html #css #javascript #webdev #programming #developer 

How to Create a Tic Tac Toe Game using HTML CSS & JavaScript

In this blog you’ll learn how to create a Tic Tac Toe Game using HTML CSS & JavaScript.

To create a Tic Tac Toe Game using HTML CSS & JavaScript . First, you need to create three files, HTML File, CSS File, and JavaScript File.

1: First, create an HTML file with the name of index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Tic Tac Toe Game | Codequs</title>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"/>
</head>
<body>
  <!-- select box -->
  <div class="select-box">
    <header>Tic Tac Toe</header>
    <div class="content">
      <div class="title">Select which you want to be?</div>
      <div class="options">
        <button class="playerX">Player (X)</button>
        <button class="playerO">Player (O)</button>
      </div>
      <div class="credit">Created By <a href="https://www.youtube.com/codequs" target="_blank">CodingNepal</a></div>
    </div>
  </div> 
  <!-- playboard section -->
  <div class="play-board">
    <div class="details">
      <div class="players">
        <span class="Xturn">X's Turn</span>
        <span class="Oturn">O's Turn</span>
        <div class="slider"></div>
      </div>
    </div>
    <div class="play-area">
      <section>
        <span class="box1"></span>
        <span class="box2"></span>
        <span class="box3"></span>
      </section>
      <section>
        <span class="box4"></span>
        <span class="box5"></span>
        <span class="box6"></span>
      </section>
      <section>
        <span class="box7"></span>
        <span class="box8"></span>
        <span class="box9"></span>
      </section>
    </div>
  </div>
  <!-- result box -->
  <div class="result-box">
    <div class="won-text"></div>
    <div class="btn"><button>Replay</button></div>
  </div>
  <script src="script.js"></script>
</body>
</html>

2: Second, create a CSS file with the name of style.css

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
::selection{
  color: #fff;
  background:#56baed;
}
body{
  background:#56baed;
}
.select-box, .play-board, .result-box{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transition: all 0.3s ease;
}
.select-box{
  background: #fff;
  padding: 20px 25px 25px;
  border-radius: 5px;
  max-width: 400px;
  width: 100%;
}
.select-box.hide{
  opacity: 0;
  pointer-events: none;
}
.select-box header{
  font-size: 30px;
  font-weight: 600;
  padding-bottom: 10px;
  border-bottom: 1px solid lightgrey;
}
.select-box .title{
  font-size: 22px;
  font-weight: 500;
  margin: 20px 0;
}
.select-box .options{
  display: flex;
  width: 100%;
}
.options button{
  width: 100%;
  font-size: 20px;
  font-weight: 500;
  padding: 10px 0;
  border: none;
  background: #56baed;
  border-radius: 5px;
  color: #fff;
  outline: none;
  cursor: pointer;
  transition: all 0.3s ease;
}
.options button:hover,
.btn button:hover{
  transform: scale(0.96);
}
.options button.playerX{
  margin-right: 5px;
}
.options button.playerO{
  margin-left: 5px;
}
.select-box .credit{
  text-align: center;
  margin-top: 20px;
  font-size: 18px;
  font-weight: 500;
}
.select-box .credit a{
  color: #56baed;
  text-decoration: none;
}
.select-box .credit a:hover{
  text-decoration: underline;
}
.play-board{
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0.9);
}
.play-board.show{
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
}
.play-board .details{
  padding: 7px;
  border-radius: 5px;
  background: #fff;
}
.play-board .players{
  width: 100%;
  display: flex;
  position: relative;
  justify-content: space-between;
}
.players span{
  position: relative;
  z-index: 2;
  color: #56baed;
  font-size: 20px;
  font-weight: 500;
  padding: 10px 0;
  width: 100%;
  text-align: center;
  cursor: default;
  user-select: none;
  transition: all 0.3 ease;
}
.players.active span:first-child{
  color: #fff;
}
.players.active span:last-child{
  color: #56baed;
}
.players span:first-child{
  color: #fff;
}
.players .slider{
  position: absolute;
  top: 0;
  left: 0;
  width: 50%;
  height: 100%;
  background: #56baed;
  border-radius: 5px;
  transition: all 0.3s ease;
}
.players.active .slider{
  left: 50%;
}
.players.active span:first-child{
  color: #56baed;
}
.players.active span:nth-child(2){
  color: #fff;
}
.players.active .slider{
  left: 50%;
}
.play-area{
  margin-top: 20px;
}
.play-area section{
  display: flex;
  margin-bottom: 1px;
}
.play-area section span{
  display: block;
  height: 90px;
  width: 90px;
  margin: 2px;
  color: #56baed;
  font-size: 40px;
  line-height: 80px;
  text-align: center;
  border-radius: 5px;
  background: #fff;
}
.result-box{
  padding: 25px 20px;
  border-radius: 5px;
  max-width: 400px;
  width: 100%;
  opacity: 0;
  text-align: center;
  background: #fff;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0.9);
}
.result-box.show{
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
}
.result-box .won-text{
  font-size: 30px;
  font-weight: 500;
  display: flex;
  justify-content: center;
}
.result-box .won-text p{
  font-weight: 600;
  margin: 0 5px;
}
.result-box .btn{
  width: 100%;
  margin-top: 25px;
  display: flex;
  justify-content: center;
}
.btn button{
  font-size: 18px;
  font-weight: 500;
  padding: 8px 20px;
  border: none;
  background: #56baed;
  border-radius: 5px;
  color: #fff;
  outline: none;
  cursor: pointer;
  transition: all 0.3s ease;
}

3: Last, create a JavaScript file with the name of script.js

const selectBox = document.querySelector(".select-box"),
selectBtnX = selectBox.querySelector(".options .playerX"),
selectBtnO = selectBox.querySelector(".options .playerO"),
playBoard = document.querySelector(".play-board"),
players = document.querySelector(".players"),
allBox = document.querySelectorAll("section span"),
resultBox = document.querySelector(".result-box"),
wonText = resultBox.querySelector(".won-text"),
replayBtn = resultBox.querySelector("button");
window.onload = ()=>{
    for (let i = 0; i < allBox.length; i++) {
       allBox[i].setAttribute("onclick", "clickedBox(this)");
    }
}
selectBtnX.onclick = ()=>{
    selectBox.classList.add("hide");
    playBoard.classList.add("show");
}
selectBtnO.onclick = ()=>{ 
    selectBox.classList.add("hide");
    playBoard.classList.add("show");
    players.setAttribute("class", "players active player");
}
let playerXIcon = "fas fa-times",
playerOIcon = "far fa-circle",
playerSign = "X",
runBot = true;
function clickedBox(element){
    if(players.classList.contains("player")){
        playerSign = "O";
        element.innerHTML = `<i class="${playerOIcon}"></i>`;
        players.classList.remove("active");
        element.setAttribute("id", playerSign);
    }else{
        element.innerHTML = `<i class="${playerXIcon}"></i>`;
        element.setAttribute("id", playerSign);
        players.classList.add("active");
    }
    selectWinner();
    element.style.pointerEvents = "none";
    playBoard.style.pointerEvents = "none";
    let randomTimeDelay = ((Math.random() * 1000) + 200).toFixed();
    setTimeout(()=>{
        bot(runBot);
    }, randomTimeDelay);
}
function bot(){
    let array = [];
    if(runBot){
        playerSign = "O";
        for (let i = 0; i < allBox.length; i++) {
            if(allBox[i].childElementCount == 0){
                array.push(i);
            }
        }
        let randomBox = array[Math.floor(Math.random() * array.length)];
        if(array.length > 0){
            if(players.classList.contains("player")){ 
                playerSign = "X";
                allBox[randomBox].innerHTML = `<i class="${playerXIcon}"></i>`;
                allBox[randomBox].setAttribute("id", playerSign);
                players.classList.add("active");
            }else{
                allBox[randomBox].innerHTML = `<i class="${playerOIcon}"></i>`;
                players.classList.remove("active");
                allBox[randomBox].setAttribute("id", playerSign);
            }
            selectWinner();
        }
        allBox[randomBox].style.pointerEvents = "none";
        playBoard.style.pointerEvents = "auto";
        playerSign = "X";
    }
}
function getIdVal(classname){
    return document.querySelector(".box" + classname).id;
}
function checkIdSign(val1, val2, val3, sign){ 
    if(getIdVal(val1) == sign && getIdVal(val2) == sign && getIdVal(val3) == sign){
        return true;
    }
}
function selectWinner(){
    if(checkIdSign(1,2,3,playerSign) || checkIdSign(4,5,6, playerSign) || checkIdSign(7,8,9, playerSign) || checkIdSign(1,4,7, playerSign) || checkIdSign(2,5,8, playerSign) || checkIdSign(3,6,9, playerSign) || checkIdSign(1,5,9, playerSign) || checkIdSign(3,5,7, playerSign)){
        runBot = false;
        bot(runBot);
        setTimeout(()=>{
            resultBox.classList.add("show");
            playBoard.classList.remove("show");
        }, 700);
        wonText.innerHTML = `Player <p>${playerSign}</p> won the game!`;
    }else{
        if(getIdVal(1) != "" && getIdVal(2) != "" && getIdVal(3) != "" && getIdVal(4) != "" && getIdVal(5) != "" && getIdVal(6) != "" && getIdVal(7) != "" && getIdVal(8) != "" && getIdVal(9) != ""){
            runBot = false;
            bot(runBot);
            setTimeout(()=>{
                resultBox.classList.add("show");
                playBoard.classList.remove("show");
            }, 700);
            wonText.textContent = "Match has been drawn!";
        }
    }
}
replayBtn.onclick = ()=>{
    window.location.reload();
}

Now you’ve successfully created a Tic Tac Toe Game using HTML CSS & JavaScript.