Hey there! We are coming back with a second tutorial for enthusiastic developers. In this series of articles, we will try to create an engaging website using React with Vite, Typescript, SCSS, and Framer Motion.
We will answer some of the questions, starting from the basics up to various hints and tricks that you may need for your product.
Here is a quick breakdown of the topics that we are going to cover in this tutorial:
Let us start!
For this project, we will be using React with Vite, Typescript, SCSS, and Framer Motion
If you already have a basic project template or you’re using another tool for project creation, you can skip this step.
npm create vite@latest
npm install
npm install --save-dev sass
We’ll need clsx for effective classNames management
npm install --save clsx
npm install --save svgr
npm install framer-motion
npm run dev
Now let’s add some assets. We’ll begin with fonts, and we will use three different ones: Roboto Serif, Roboto Slab, and Modernist
/* ./src/styles/abstracts/fonts.scss */
@font-face {
font-family: 'RobotoSerif-RegularItalic';
font-display: swap;
src: local('RobotoSerif-RegularItalic'), url(../../assets/fonts/RobotoSerif/RobotoSerif-RegularItalic.ttf) format('truetype');
}
Notice that we use font-display: swap. The font swap period occurs immediately after the font block period. During this period, if the font face is not loaded, any element attempting to use it must instead render with a fallback font face. If the font face successfully loads during the swap period, it is then used normally.
We’ll also add these fonts to the variables
/* ./src/styles/abstracts/variables.scss */
/* ... */
$font-italic-regular: 'RobotoSerif-RegularItalic';
$font-title-semi-bold: 'RobotoSlab-SemiBold';
$font-title-bold: 'RobotoSlab-Bold';
$font-title-extra-bold: 'RobotoSlab-ExtraBold';
$font-main-bold: 'SkModernist-Bold';
$font-main-regular: 'SkModernist-Regular';
/* ... */
Our website needs to support several different display resolutions, which is why we also add some breakpoints in variables for future usage
/* ./src/styles/abstracts/variables.scss */
/* … */
$break-points: (
small: 600px,
medium: 992px,
large: 1350px,
);
/* … */
Images that we are going to use are stored in ./src/assets/images in PNG format for now; we will optimize them later
Let’s also reset some of the default browser styles:
/* ./src/styles/globas.scss */
@use './abstracts' as *;
*, *::after, *::before, {
box-sizing: border-box;
}
html, body {
padding: 0;
margin: 0;
background: $background;
font-family: $font-main-regular;
}
h1, h2, h3, h4, p {
margin: 0;
}
.home {
position: relative;
width: 100vw;
min-height: 100vh;
overflow: hidden;
}
Now we need to define some TypeScript Interfaces, constants, and enums
Let’s start with the constants to define periods, countries, and subjects
// ./src/constants.ts
export enum Periods {
Viking = 'Viking age',
Assimilation = 'Assimilation',
}
export enum Countries {
Norway = 'Norway',
Sweden = 'Sweden',
Denmark = 'Denmark',
Norden = 'Norden',
}
export enum Subjects {
History = 'History',
Culture = 'Culture',
}
We need to define data interfaces for consistency, we’ll also use enums here from above. You can read more about Interfaces and Mapped types in Typescript documentation
// ./src/types.ts
import { Countries, Periods, Subjects } from './constants';
export interface PeriodItemInterface {
name: Periods;
primaryColor: string;
secondaryColor: string;
imagePath: string;
quotationText: string;
quotationAuthor: string;
}
export type PeriodsDataInterface = {
[Key in Periods]: PeriodItemInterface;
};
export interface InfoItemInterface {
primaryColor: string;
secondaryColor: string;
imagePath: string;
textBlocks: {
left: string[];
right: string[];
};
}
type CountryDataInterface = {
[Key in Countries]: InfoItemInterface;
};
type SubjectDataInterface = {
[Key in Subjects]: CountryDataInterface;
};
export type DataInterface = {
[Key in Periods]: SubjectDataInterface;
};
And then use these interfaces for our static data
// ./src/data.ts
export const periodsData: PeriodsDataInterface = {
[Periods.Viking]: {
name: Periods.Viking,
primaryColor: '#B898FB',
secondaryColor: '#3D006C',
imagePath: VikingAgeImagePath,
quotationText:
'The Vikings were a fascinating people...',
quotationAuthor: 'Judith Jesch',
},
//...
};
export const data: DataInterface = {
[Periods.Viking]: {
[Subjects.History]: {
[Countries.Norway]: {
primaryColor: '#2B766C',
secondaryColor: '#982020',
imagePath: VikingAgeHistoryNorwayImage,
textBlocks: {
left: [
'The Viking Age is a period...',
'The Viking Age began...',
],
right: [
'In Norway, the Viking Age...',
],
},
},
},
},
//...
};
That’s it for today’s part of our tutorial. Let’s recap what we have done already:
That’s a great deal of work; well done! We will be proceeding with this project in Part 2 of this tutorial. See you soon!
30.08.2023
Bespoke Software Vs. Off-The-Shelf Stuff: Pros & ConsThere’s no doubt that in time, you want your business to scale and capture a better share of the market. The key to making everything work is building all of your operations on the right software that can help you boost productivity and keep up with customer demands. Here, you have two choices: Custom or off-the-shelf software. We’ll help you make the choice by outlining the pros and cons of custom software vs. off-the-shelf software.Read more27.08.2023
The Perfect Roadmap for Budget Planning in Software DevelopmentThere are many people who prefer custom software development to optimize internal operations. Some may also want to develop software that sells great to clients. It doesn't matter what kind of software you're creating, creating your own software from scratch is a massive job. This blog explains why budgeting your software development costs right is the best way to keep costs under control,Read more04.08.2023
How to Create a Website Using React and Framer Motion: Complete Tutorial, Part 2Hey there! Welcome back to the second part of our tutorial for enthusiastic developers, where we create an engaging website using React with Vite, Typescript, SCSS, and Framer Motion.Read more