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!
24.12.2023
Agile vs Waterfall Software Development Methods: 7 Key DifferencesAgile and Waterfall are the two most prominent methods in the software development industry today. Although they are both solid and offer the most practical way to finish a project as quickly as possible, they're different in many ways. Here are 7 of them.Read more22.12.2023
How to Build a Tool for Generating Linear and Radial Gradients with React: Complete Tutorial, Part 3Hello! Welcome back to part three of our tutorial for excited developers. In this tutorial, We'll use React for our app, utilize the react-colorful library for color manipulation, add smooth animations with framer-motion, ensure type safety with TypeScript, and style our app using Sass.Read more22.12.2023
How to Build a Tool for Generating Linear and Radial Gradients with React: Complete Tutorial, Part 2Hello! Welcome back to part two of our tutorial for excited developers. In this tutorial, We'll use React for our app, utilize the react-colorful library for color manipulation, add smooth animations with framer-motion, ensure type safety with TypeScript, and style our app using Sass.Read more