On this blog post, I'll be documenting the steps taken to build a static responsive Next.js website using Tailwind CSS.
This is a work in progress, and currently, the app looks like this.
mkdir nextjs-tailwindcss
cd nextjs-tailwindcss
node -v
My terminal outputted:
v20.9.0
npx create-next-app@latest .
I answered No to all of questions that were prompted:
Need to install the following packages:
create-next-app@14.0.2
Ok to proceed? (y) y
✔ Would you like to use TypeScript? … No
✔ Would you like to use ESLint? … No
✔ Would you like to use Tailwind CSS? … No
✔ Would you like to use `src/` directory? … No
✔ Would you like to use App Router? (recommended) … No
✔ Would you like to customize the default import alias (@/*)? … No
When you don't use the new App Router (recommended), the pages directory is available and on the contrary, when using the App Router, the pages directory isn't available.
The App Router is new and I'll have to explore using the App Router in a future post without the pages directory, and see how things work alternatively.
npm run dev
http://localhost:3000
At this point, a Next.js app boilerplate website is displayed.
Home.module.css
./styles/Home.module.css
Error: ENOENT: no such file or directory, open '/Users/eugene/Desktop/nextjs-tailwindcss/styles/Home.module.css'
Import trace for requested module:
./styles/Home.module.css
./pages/index.js
import Head from 'next/head'
import Image from 'next/image'
import { Inter } from 'next/font/google'
- import styles from '@/styles/Home.module.css'
14 | <link rel="icon" href="/favicon.ico" />
15 | </Head>
> 16 | <main className={`${styles.main} ${inter.className}`}>
| ^
17 | <div className={styles.description}>
18 | <p>
19 | Get started by editing
import Head from 'next/head'
- import Image from 'next/image'
- import { Inter } from 'next/font/google'
- const inter = Inter({ subsets: ['latin'] })
export default function Home() {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
- <main className={`${styles.main} ${inter.className}`}>
- <div className={styles.description}>
- <p>
- Get started by editing
- <code className={styles.code}>pages/index.js</code>
- </p>
- <div>
- <a
- href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
- target="_blank"
- rel="noopener noreferrer"
- >
- By{' '}
- <Image
- src="/vercel.svg"
- alt="Vercel Logo"
- className={styles.vercelLogo}
- width={100}
- height={24}
- priority
- />
- </a>
- </div>
- </div>
-
- <div className={styles.center}>
- <Image
- className={styles.logo}
- src="/next.svg"
- alt="Next.js Logo"
- width={180}
- height={37}
- priority
- />
- </div>
-
- <div className={styles.grid}>
- <a
- href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
- className={styles.card}
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2>
- Docs <span>-></span>
- </h2>
- <p>
- Find in-depth information about Next.js features and API.
- </p>
- </a>
-
- <a
- href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
- className={styles.card}
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2>
- Learn <span>-></span>
- </h2>
- <p>
- Learn about Next.js in an interactive course with quizzes!
- </p>
- </a>
-
- <a
- href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
- className={styles.card}
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2>
- Templates <span>-></span>
- </h2>
- <p>
- Discover and deploy boilerplate example Next.js projects.
- </p>
- </a>
-
- <a
- href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
- className={styles.card}
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2>
- Deploy <span>-></span>
- </h2>
- <p>
- Instantly deploy your Next.js site to a shareable URL
- with Vercel.
- </p>
- </a>
- </div>
- </main>
</>
)
}
import Head from 'next/head'
export default function Home() {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
</>
)
}
- :root {
- --max-width: 1100px;
- --border-radius: 12px;
- --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
- 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
- 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
-
- --foreground-rgb: 0, 0, 0;
- --background-start-rgb: 214, 219, 220;
- --background-end-rgb: 255, 255, 255;
-
- --primary-glow: conic-gradient(
- from 180deg at 50% 50%,
- #16abff33 0deg,
- #0885ff33 55deg,
- #54d6ff33 120deg,
- #0071ff33 160deg,
- transparent 360deg
- );
- --secondary-glow: radial-gradient(
- rgba(255, 255, 255, 1),
- rgba(255, 255, 255, 0)
- );
-
- --tile-start-rgb: 239, 245, 249;
- --tile-end-rgb: 228, 232, 233;
- --tile-border: conic-gradient(
- #00000080,
- #00000040,
- #00000030,
- #00000020,
- #00000010,
- #00000010,
- #00000080
- );
-
- --callout-rgb: 238, 240, 241;
- --callout-border-rgb: 172, 175, 176;
- --card-rgb: 180, 185, 188;
- --card-border-rgb: 131, 134, 135;
- }
-
- @media (prefers-color-scheme: dark) {
- :root {
- --foreground-rgb: 255, 255, 255;
- --background-start-rgb: 0, 0, 0;
- --background-end-rgb: 0, 0, 0;
-
- --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
- --secondary-glow: linear-gradient(
- to bottom right,
- rgba(1, 65, 255, 0),
- rgba(1, 65, 255, 0),
- rgba(1, 65, 255, 0.3)
- );
-
- --tile-start-rgb: 2, 13, 46;
- --tile-end-rgb: 2, 5, 19;
- --tile-border: conic-gradient(
- #ffffff80,
- #ffffff40,
- #ffffff30,
- #ffffff20,
- #ffffff10,
- #ffffff10,
- #ffffff80
- );
-
- --callout-rgb: 20, 20, 20;
- --callout-border-rgb: 108, 108, 108;
- --card-rgb: 100, 100, 100;
- --card-border-rgb: 200, 200, 200;
- }
- }
-
- * {
- box-sizing: border-box;
- padding: 0;
- margin: 0;
- }
-
- html,
- body {
- max-width: 100vw;
- overflow-x: hidden;
- }
-
- body {
- color: rgb(var(--foreground-rgb));
- background: linear-gradient(
- to bottom,
- transparent,
- rgb(var(--background-end-rgb))
- )
- rgb(var(--background-start-rgb));
- }
-
- a {
- color: inherit;
- text-decoration: none;
- }
-
- @media (prefers-color-scheme: dark) {
- html {
- color-scheme: dark;
- }
- }
-
api/hello.js
favicon.ico
next.svg
vercel.svg
Next, I needed to install and setup Tailwind CSS so I navigated over to tailwindcss.com and clicked Get started which directed me over to the Installation page.
Within the Installation page, I clicked the Framework Guides and clicked Next.js.
I skipped down to step 2 of the guide, copied the following command, stopped the development server, and installed Tailwind CSS by pasting, and executing the command:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
tailwind.config.js
postcss.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
// Or if using `src` directory:
"./src/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {},
},
plugins: [],
}
// @tailwind base; /* Preflight will be injected here */
// @tailwind components;
// @tailwind utilities;
The Tailwind CSS directives are commented out so they're not taken into effect right now.
Basically, the directive @tailwindcss base will inject Preflight base styles which will serve to reset and standardize styles to ensure a consistent starting point for styling across different browsers and elements.
Soon as these directives are commented back in and the file saved, a noticeable change will be displayed which will be observed in step 34.
At this point, Tailwind CSS is almost ready to be used.
Then, I needed a font Tailwind CSS doesn't provide, so I went to Google Fonts, searched for the "Montserrat Alternates" font, selected it, and further selected the following styles:
Once done adding the styles, I copied the import statement that was generated by Google Fonts under "Use on the Web" and pasted it at the top of the globals.css file as such:
@import url('https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght@100;200;300;400;500;600;700;800&display=swap');
// @tailwind base; /* Preflight will be injected here */
// @tailwind components;
// @tailwind utilities;
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
// Or if using `src` directory:
"./src/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontFamily: {
'html': ['Montserrat Alternates', 'Arial', 'sans-serif']
}
},
},
plugins: [],
}
I added a new key called "fontFamily" and assigned it a new object in the "extend" object which is in the "theme" object.
Then, I added a new key called "html" in the "fontFamily" object and assiged it a new array of fonts which includes the "Montserrat Alternates" font that was imported earlier into the globals.css file in step 27 along with a couple fallback fonts.
At this point, the "Montserrat Alternates" font is ready to be applied using the custom Tailwind CSS that was just configured.
components
Hero.jsx
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className=''>
{/*Hero Background Image */}
{/*Hero Background Overlay */}
<div className='' />
{/*Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Head from 'next/head'
import Hero from '../components/Hero';
export default function Home() {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Hero />
</>
)
}
npm run serve
At this point, the browser is displaying the Hero content.
@import url('https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght@100;200;300;400;500;600;700;800&display=swap');
@tailwind base; /* Preflight will be injected here */
@tailwind components;
@tailwind utilities;
Soon as the globals.css was saved, the styling was removed because of Tailwind CSS's Preflight base styling being applied on line 2 of the globals.css file.
@import url('https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght@100;200;300;400;500;600;700;800&display=swap');
@tailwind base; /* Preflight will be injected here */
@tailwind components;
@tailwind utilities;
The Tailwind CSS directive for base styleing removes styling so there isn't any styling despite having used a h2, p, and a button element in the Hero component which intrinsically has styling.
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html lang="en" className='font-html scroll-smooth'>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
The "html" key that was added under the "fontFamily" object associated to the "Montserrat Alternates" font in the tailwind.config.js file is now being applied by using the "font-html" Tailwind CSS custom class.
Additionally, the "smooth-scroll" Tailwind CSS class has been applied so scrolling will be animated and gradual rather than instantaneous when navigating to an achor within the page.
Furthermore, if you hover over the class names (e.g. "font-html" or "scroll-smooth"), the CSS definition is displayed via the Visual Code extension, Tailwind CSS IntelliSense, installed in step 25, so you know what Tailwind CSS is doing underneath the hood in terms of CSS.
Soon as the tailwind.config.js file is saved, notice how the font, 'Montserrat Alternates', and the smooth scrolling behavior is applied.
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative'>
{/*Hero Background Image */}
{/*Hero Background Overlay */}
<div className='' />
{/*Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
The descendants of the Hero Container are the Hero Background Image, the Hero Background Overlay, and the Hero Content.
With the Hero Container having a position of relative, the descendants or children can now be positioned relative to its parent, the Hero Container, and allows the use of z-index to assign each child a stacking order since the children will be stacked on top of each other, first starting with the Hero Background Image, then second, the Background Overlay, and third, the Hero Content.
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex'>
{/*Hero Background Image */}
{/*Hero Background Overlay */}
<div className='' />
{/*Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
The flex Tailwind CSS class is be used to set the layout of the Hero component so the elements can be positioned as needed.
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center'>
{/*Hero Background Image */}
{/*Hero Background Overlay */}
<div className='' />
{/*Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
The content is now centered horizontally along the x-axis.
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-full'>
{/*Hero Background Image */}
{/*Hero Background Overlay */}
<div className='' />
{/*Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-full items-center'>
{/*Hero Background Image */}
{/*Hero Background Overlay */}
<div className='' />
{/*Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
Now, the Hero content is centered vertically along the y-axis.
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-full items-center mb-12'>
{/*Hero Background Image */}
{/*Hero Background Overlay */}
<div className='' />
{/*Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
Now the Hero component has a bottom margin of 48 pixels or 3 rem or 3 times larger than the root element's font size of 16 pixels.
import Image from 'next/image';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image />
{/* Hero Background Overlay */}
<div className='' />
{/* Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
images/convictlake.jpg
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image src={heroBackgroundImage} />
{/* Hero Background Overlay */}
<div className='' />
{/* Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
At this point, the Hero Background Image is positioned to the left of the Hero Content because they are flex items.
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
/>
{/* Hero Background Overlay */}
<div className='' />
{/* Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
At this point, the Hero Background Image is filling the entire parent Hero Container div element and is displayed on top of the Hero Content which is no longer visible because it is behind the Hero Background Image now.
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover'
/>
{/* Hero Background Overlay */}
<div className='' />
{/* Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
Now, when you adjust the screen size from small to big, the Hero Background Image preserves its aspect ratio.
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
/>
{/* Hero Background Overlay */}
<div className='' />
{/* Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='' />
{/* Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className=''>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
Now a black background that's 50% transparent completely overlays the background image.
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0'>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0 text-white'>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0 text-white p-5'>
<h2 className=''>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0 text-white p-5 text-center'>
<h2 className='text-6xl uppercase'>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0 text-white p-5 text-center'>
<h2 className='text-6xl uppercase'>Heading</h2>
<p className=''>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0 text-white p-5 text-center'>
<h2 className='text-6xl uppercase'>Heading</h2>
<p className='text-2xl'>Message</p>
<button className=''>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero() {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0 text-white p-5 text-center'>
<h2 className='text-6xl uppercase'>Heading</h2>
<p className='text-2xl'>Message</p>
<button className='px-6 py-1 border mt-2'>Button</button>
</div>
</div>
</>
);
};
import Image from 'next/image';
import heroBackgroundImage from '../public/images/convictlake.jpg';
export default function Hero({ heading, message }) {
return (
<>
{/* Hero Container */}
<div className='relative flex justify-center h-screen items-center mb-12'>
{/* Hero Background Image */}
<Image
src={heroBackgroundImage}
fill='true'
className='object-cover object-left'
alt='Eugene fishing'
/>
{/* Hero Background Overlay */}
<div className='absolute top-0 left-0 right-0 bottom-0 bg-black/50' />
{/* Hero Content */}
<div className='z-0 text-white p-5 text-center'>
<h2 className='text-6xl uppercase'>{ heading }</h2>
<p className='text-2xl'>{ message }</p>
<button className='px-6 py-1 border mt-2'>Button</button>
</div>
</div>
</>
);
};
import Head from 'next/head'
import Hero from '../components/Hero';
export default function Home() {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Hero heading='Eugene Kim' message='Software Engineer' />
</>
)
}
Now, the page is being rendered with text being passed into the Hero component from the entry point of the app, the index.js file.
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor}`}>
{/*The Navigation Bar Inner Container */}
<div className=''>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor}`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor}`}>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className=''>
{
isMobileMenuDislayed ? <button className=''>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className=''>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor}`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor}`}>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className=''>
{
isMobileMenuDislayed ? <button className=''>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor}`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor}`}>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className=''>
{
isMobileMenuDislayed ? <button className=''>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor}`}>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className=''>
{
isMobileMenuDislayed ? <button className=''>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>About</li>
<li className='p-4'>Work</li>
<li className='p-4'>Blog</li>
<li className='p-4'>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className=''>
{
isMobileMenuDislayed ? <button className=''>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>About</li>
<li className='p-4'>Work</li>
<li className='p-4'>Blog</li>
<li className='p-4'>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className=''>
{
isMobileMenuDislayed ? <button className=''>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>About</li>
<li className='p-4'>Work</li>
<li className='p-4'>Blog</li>
<li className='p-4'>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className='sm:hidden z-10'>
{
isMobileMenuDislayed ? <button className=''>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className=''>About</li>
<li className=''>Work</li>
<li className=''>Blog</li>
<li className=''>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>About</li>
<li className='p-4'>Work</li>
<li className='p-4'>Blog</li>
<li className='p-4'>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className='sm:hidden z-10'>
{
isMobileMenuDislayed ? <button className='text-white'>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className='p-4 text-4xl hover:text-white'>About</li>
<li className='p-4 text-4xl hover:text-white'>Work</li>
<li className='p-4 text-4xl hover:text-white'>Blog</li>
<li className='p-4 text-4xl hover:text-white'>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>About</li>
<li className='p-4'>Work</li>
<li className='p-4'>Blog</li>
<li className='p-4'>Contact</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className='sm:hidden z-10'>
{
isMobileMenuDislayed ? <button className='text-white'>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className='p-4 text-4xl hover:text-white'>About</li>
<li className='p-4 text-4xl hover:text-white'>Work</li>
<li className='p-4 text-4xl hover:text-white'>Blog</li>
<li className='p-4 text-4xl hover:text-white'>Contact</li>
</ul>
</div>
</div>
</div>
</>
);
}
import Link from 'next/link';
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const backgroundColor = '';
const textColor = '';
// The variable for storing the boolean used for presenting the mobile menu
const isMobileMenuDislayed = false;
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<Link href='/'>
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
</Link>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>
<Link href='/about'>About</Link>
</li>
<li className='p-4'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className='sm:hidden z-10'>
{
isMobileMenuDislayed ? <button className='text-white'>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/about'>About</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
</div>
</div>
</div>
</>
);
}
import Link from 'next/link';
import { useState } from 'react';
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const [backgroundColor, setBackgroundColor] = useState('bg-transparent');
const [textColor, setTextColor] = useState('text-white');
// The variable for storing the boolean used for presenting the mobile menu
const [isMobileMenuDislayed, setIsMobileMenuDisplayed] = useState(false);
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<Link href='/'>
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
</Link>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>
<Link href='/about'>About</Link>
</li>
<li className='p-4'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className='sm:hidden z-10'>
{
isMobileMenuDislayed ? <button className='text-white'>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/about'>About</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
</div>
</div>
</div>
</>
);
}
import Link from 'next/link';
import { useState, useEffect } from 'react';
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const [backgroundColor, setBackgroundColor] = useState('bg-transparent');
const [textColor, setTextColor] = useState('text-white');
// The variable for storing the boolean used for presenting the mobile menu
const [isMobileMenuDislayed, setIsMobileMenuDisplayed] = useState(false);
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
useEffect(() => {
const changeColor = () => {
if (window.scrollY >= 90) {
setBackgroundColor('bg-white');
setTextColor('text-black');
} else {
setBackgroundColor('bg-transparent');
setTextColor('text-white');
}
};
window.addEventListener('scroll', changeColor);
}, []);
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<Link href='/'>
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
</Link>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>
<Link href='/about'>About</Link>
</li>
<li className='p-4'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick='' className='sm:hidden z-10'>
{
isMobileMenuDislayed ? <button className='text-white'>close</button>
: <button className={`${textColor}`}>open</button>
}
</div>
{/*The Mobile Menu */}
<div className={ isMobileMenuDislayed ? '' : '' }>
<ul>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/about'>About</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
</div>
</div>
</div>
</>
);
}
import Link from 'next/link';
import { useState, useEffect } from 'react';
import { AiOutlineMenu, AiOutlineClose } from 'react-icons/ai';
export default function Navbar() {
// The variables for storing the colors of the navigation bar
const [backgroundColor, setBackgroundColor] = useState('bg-transparent');
const [textColor, setTextColor] = useState('text-white');
// The variable for storing the boolean used for presenting the mobile menu
const [isMobileMenuDislayed, setIsMobileMenuDisplayed] = useState(false);
// The function that will respond to clicks of the mobile menu buttons and presenting the mobile menu
const handleMobileMenu = () => {
setIsMobileMenuDisplayed(!isMobileMenuDislayed);
}
// The function that will respond to scrolling on the browser window and presenting the colors of the navigation bar
useEffect(() => {
const changeColor = () => {
if (window.scrollY >= 90) {
setBackgroundColor('bg-white');
setTextColor('text-black');
} else {
setBackgroundColor('bg-transparent');
setTextColor('text-white');
}
};
window.addEventListener('scroll', changeColor);
}, []);
return (
<>
{/* The Navigation Bar Outer Container */}
<div className={`${backgroundColor} fixed left-0 top-0 w-full z-10 ease-in duration-300`}>
{/*The Navigation Bar Inner Container */}
<div className='max-w-[1240px] m-auto flex justify-between items-center p-4'>
{/*The Navigation Bar Logo */}
<Link href='/'>
<h1 className={`${textColor} font-bold text-4xl`}>E</h1>
</Link>
{/*The Navigation Bar Links */}
<ul className={`${textColor} hidden sm:flex`}>
<li className='p-4'>
<Link href='/about'>About</Link>
</li>
<li className='p-4'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
{/*The Mobile Menu Buttons */}
<div onClick={handleMobileMenu} className='sm:hidden z-10'>
{
isMobileMenuDislayed ?
<AiOutlineClose className='text-white' size={20} />
:
<AiOutlineMenu className={`${textColor}`} size={20} />
}
</div>
{/*The Mobile Menu */}
<div className={
isMobileMenuDislayed ?
'sm:hidden absolute top-0 left-0 right-0 bottom-0 flex justify-center items-center w-full h-screen bg-black text-center ease-in duration-300 text-white'
:
'sm:hidden absolute top-0 left-[-100%] right-0 bottom-0 flex justify-center items-center w-full h-screen bg-black text-center ease-in duration-300 text-white'
}>
<ul>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/about'>About</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/work'>Work</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/blog'>Blog</Link>
</li>
<li className='p-4 text-4xl hover:text-white'>
<Link href='/contact'>Contact</Link>
</li>
</ul>
</div>
</div>
</div>
</>
);
}