Learn
🤖 AI Hub 📰 News 📖 Dictionary 🧰 Resources
Grow
💼 Jobs 🚀 Community 🏆 Challenges
Explore by Stage
🌑 Zero 📚 Learn 🔧 Practice 🏗 Build 🚀 Launch 💰 Earn
Account
Login Sign Up
🏗️HTML 🎨CSS ⚡JavaScript 🐙Git & GitHub ⚛️React Soon 📘TypeScript Soon 🐍Python 🗄️Database & SQL Soon 🌐Web Development Soon ☁️Cloud & DevOps Soon 🤖AI & ML Soon 📄Resume Prep Soon 🎤Interview Prep Soon 💼Freelancing Soon 🚀SaaS & Side Projects Soon 🤖Automation Soon
Beginner 🕑 15 min read 👁 2 views 📅 Oct 21, 2026

Fonts in CSS: font-family, Google Fonts and Readable Text

Learn how font-family and fallbacks work, add free Google Fonts (including a Hindi font) and use weight, line-height and letter-spacing to design a readable wedding invitation page.

Why Fonts Matter: A Wedding Invitation Card

Think about the last wedding card your family received. Before anyone read a single word, the card already told you something. Curly golden letters said “this is a grand celebration”. A clean, simple font for the date and venue said “this part is important, read it carefully”.

Fonts do the same job on a web page. The right font makes a page feel friendly, serious or festive. The wrong font, or a badly spaced one, makes people stop reading. In this lesson you will design a wedding invitation web page for Ananya and Rohan, and on the way you will learn how to choose fonts, load free fonts from Google Fonts, show Hindi text beautifully and make any text comfortable to read.

In the CSS Colors and Typography lesson you already met font-size, font-weight and line-height. Here we go deeper: how the browser picks a font, what happens when a font is missing, and how to use spacing like a designer.

font-family: A List, Not a Single Font

The font-family property tells the browser which font to use. The important idea is that you give it a list of fonts, separated by commas. The browser tries the first one. If that font is not available on the visitor’s device, it tries the next one, and so on.

This list is called a font stack, and the later fonts are called fallbacks. It is like a wedding caterer’s plan: “We will serve gulab jamun. If that runs out, rasgulla. If that also runs out, any sweet.”

The last item should always be a generic family. A generic family is not a real font name. It is a type of font, and every browser has one ready:

Generic familyWhat it looks likeGood for
serifLetters with small “feet” at the endsFormal headings, invitations, books
sans-serifClean letters without feetBody text on screens, apps
monospaceEvery letter has the same widthCode, ticket numbers
cursiveLooks like handwritingRarely, it varies a lot between devices

Font names with spaces, like "Times New Roman", go inside quotes. Generic family names never take quotes. Run this example and look at the last line: the font does not exist, so the browser quietly uses sans-serif instead.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Generic Font Families</title>
  <style>
    .serif     { font-family: Georgia, "Times New Roman", serif; }
    .sans      { font-family: Arial, Helvetica, sans-serif; }
    .mono      { font-family: "Courier New", monospace; }
    .unknown   { font-family: "My Dream Font", sans-serif; }
    p { font-size: 20px; }
  </style>
</head>
<body>
  <p class="serif">Serif: letters with small feet. Classic and formal.</p>
  <p class="sans">Sans-serif: clean letters with no feet. Easy on screens.</p>
  <p class="mono">Monospace: every letter is the same width.</p>
  <p class="unknown">This font does not exist, so the browser uses the fallback.</p>
</body>
</html>

System font stacks

Every phone and laptop already has a good font built in. Windows uses Segoe UI, Android uses Roboto, and Apple devices use San Francisco. A system font stack asks the browser to use whatever the device already has. The page loads instantly because nothing needs to be downloaded, and it feels familiar to the user.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>System Font Stack</title>
  <style>
    body {
      font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
      font-size: 18px;
    }
  </style>
</head>
<body>
  <h2>Order Status</h2>
  <p>Your order has been packed and will reach you tomorrow.</p>
  <p>This text uses the font that your own phone or laptop already uses.</p>
</body>
</html>

system-ui means “the normal font of this operating system”. The names after it are fallbacks for older browsers. This is a smart choice for dashboards, forms and apps.

Adding a Google Font

Sometimes the built-in fonts are not enough. A wedding card deserves something special. Google Fonts (fonts.google.com) is a free library of more than a thousand fonts that anyone can use, even on commercial websites.

Using one takes two steps:

  1. On fonts.google.com, open a font, choose the weights you need and copy the <link> code it gives you. Paste it inside the <head> of your page, before your <style>.
  2. Use the font name in font-family, with a fallback after it.

Here we load two fonts: Playfair Display, an elegant serif for the names, and Poppins, a clean sans-serif for the details.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Google Fonts Test</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Poppins:wght@400;600&display=swap" rel="stylesheet">
  <style>
    h2 { font-family: "Playfair Display", Georgia, serif; font-size: 36px; }
    p  { font-family: "Poppins", Arial, sans-serif; font-size: 17px; }
  </style>
</head>
<body>
  <h2>Ananya weds Rohan</h2>
  <p>Together with their families, they invite you to celebrate their wedding.</p>
</body>
</html>

Look at the link address. family=Poppins:wght@400;600 means “Poppins, in weights 400 and 600 only”. Each extra weight is another file to download, so ask only for what you use. display=swap tells the browser to show the text in a fallback font first and swap to the new font when it arrives, so visitors never stare at a blank page. The two preconnect lines are optional. They help the browser start connecting to Google’s servers a little earlier.

Google Fonts load from the internet. If you open your page offline, or the connection is slow, the browser shows your fallback font instead. That is exactly why the fallback list matters. Always end with a generic family.

Fonts for Hindi and other Indian scripts

Many fonts only contain English letters. If you write Hindi in such a font, the browser borrows letters from some other font, and the result can look mismatched. For Devanagari text (Hindi, Marathi, Sanskrit), choose a font that is designed for it, such as Noto Sans Devanagari or Hind. Google Fonts also has Noto fonts for Tamil, Bengali, Telugu, Gujarati and other scripts.

<!DOCTYPE html>
<html lang="hi">
<head>
  <meta charset="UTF-8">
  <title>Hindi Font</title>
  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari:wght@400;700&display=swap" rel="stylesheet">
  <style>
    body {
      font-family: "Noto Sans Devanagari", sans-serif;
      font-size: 22px;
    }
    h2 { font-weight: 700; }
  </style>
</head>
<body>
  <h2>शुभ विवाह</h2>
  <p>आप सपरिवार सादर आमंत्रित हैं।</p>
  <p>English words also work: Reception at 7 PM.</p>
</body>
</html>

Notice lang="hi" on the <html> tag. It tells the browser and screen readers that the page is in Hindi.

font-weight and font-style

font-weight controls how thick the letters are. You can use the words normal (same as 400) and bold (same as 700), or numbers from 100 to 900. font-style: italic makes the letters slant. Use italic for short pieces like a quote or the word “and” between two names, never for whole paragraphs.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Weight and Style</title>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,400;0,600;0,800;1,400&display=swap" rel="stylesheet">
  <style>
    body { font-family: "Poppins", sans-serif; font-size: 20px; }
    .light  { font-weight: 300; }
    .normal { font-weight: 400; }
    .semi   { font-weight: 600; }
    .heavy  { font-weight: 800; }
    .italic { font-style: italic; }
  </style>
</head>
<body>
  <p class="light">300: Light, for big soft headings</p>
  <p class="normal">400: Normal, for body text</p>
  <p class="semi">600: Semi bold, for names and labels</p>
  <p class="heavy">800: Extra bold, use rarely</p>
  <p class="italic">Italic: for a short quote or a note</p>
</body>
</html>

A weight only looks right if that weight was loaded. In this example the link asks for 300, 400, 600, 800 and one italic (ital,wght@0,300;...;1,400, where 1 means italic). If you ask for font-weight: 700 but only loaded 400, the browser makes a “fake bold” by thickening the letters, which often looks blurry.

line-height and letter-spacing: Space Makes Text Readable

line-height is the space taken by each line of text. For paragraphs, a value between 1.5 and 1.8 is comfortable. Write it without a unit, like 1.7. A number without a unit means “1.7 times the font size”, and it adjusts by itself when the font size changes. Big headings look better with a tighter value, around 1.1 to 1.3.

letter-spacing adds space between letters. A small amount, like 0.1em to 0.2em, makes short UPPERCASE labels look neat and premium. Never add it to long paragraphs: it makes words harder to recognise.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Line Height and Letter Spacing</title>
  <style>
    body { font-family: Arial, sans-serif; font-size: 17px; max-width: 420px; }
    .cramped { line-height: 1; }
    .comfy   { line-height: 1.7; }
    .label {
      text-transform: uppercase;
      letter-spacing: 0.15em;
      font-size: 13px;
    }
  </style>
</head>
<body>
  <p class="label">Wedding Programme</p>
  <p class="cramped">Line height 1: the lines sit too close. Long paragraphs like this one feel heavy and the eye easily jumps to the wrong line while reading.</p>
  <p class="comfy">Line height 1.7: the lines have room to breathe. Long paragraphs like this one feel light and the eye finds the next line easily.</p>
</body>
</html>

Two fonts are enough

Designers have a simple rule: use at most two fonts on a page, one for headings and one for body text. A third font is acceptable only for a special job, like a second script such as Devanagari. More fonts make a page slower and messy, like a wedding card printed in six different styles.

Real-Life Example: Ananya and Rohan’s Wedding Invitation

Now let us put everything together. The invitation uses Playfair Display for the couple’s names, Poppins for the details and Noto Sans Devanagari for the traditional blessing at the top. Spacing does the rest: wide letter-spacing on the small labels, comfortable line-height everywhere and a tight line-height on the big heading.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Ananya and Rohan: Wedding Invitation</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,700;1,400&family=Poppins:wght@400;600&family=Noto+Sans+Devanagari:wght@400&display=swap" rel="stylesheet">
  <style>
    body {
      font-family: "Poppins", system-ui, sans-serif;
      font-size: 17px;
      line-height: 1.7;
      color: #4a2c2a;
      background-color: #fff8ee;
      text-align: center;
      padding: 24px;
    }
    .blessing {
      font-family: "Noto Sans Devanagari", sans-serif;
      font-size: 20px;
      color: #b5651d;
    }
    .label {
      font-size: 13px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.2em;
    }
    h2 {
      font-family: "Playfair Display", Georgia, serif;
      font-size: 40px;
      font-weight: 700;
      line-height: 1.2;
      margin: 8px 0;
    }
    .and {
      font-family: "Playfair Display", Georgia, serif;
      font-style: italic;
      font-weight: 400;
    }
    .details { font-weight: 600; }
  </style>
</head>
<body>
  <p class="blessing">॥ श्री गणेशाय नमः ॥</p>
  <p class="label">You are invited to the wedding of</p>
  <h2>Ananya <span class="and">and</span> Rohan</h2>
  <p>With the blessings of our elders, we request the pleasure of your company.</p>
  <p class="details">Sunday, 14 February<br>Muhurat at 11:30 AM</p>
  <p>Shubh Mangal Banquet Hall, Station Road, Indore</p>
  <p class="label">Lunch to follow</p>
</body>
</html>

Try these changes, one at a time:

  1. Replace "Playfair Display" with another Google Font, such as "Cormorant Garamond". Remember to change the link too.
  2. Change the body line-height to 1.1 and notice how crowded the card feels. Then set it back.
  3. Remove the whole Google Fonts <link> line and run it again. The page still works, because every font has a fallback.

Common Mistakes (and How to Fix Them)

  • A spelling mistake in the font name. The name must match Google Fonts exactly. "Poppin" is not "Poppins". The browser does not show an error, it simply uses a default font.
  • No fallback. Without a generic family at the end, a slow connection can show Times New Roman on your modern design.
  • Using a weight you did not load. You get fake bold or no change at all. Add the weight to the link.
  • letter-spacing on Hindi text. Devanagari letters join along the top line (the shirorekha). Extra letter-spacing can break that line into pieces. Keep letter-spacing for English labels only.
  • Forgetting the link tag. Writing font-family: "Poppins" alone does nothing on devices that do not have Poppins installed.

Here is a broken heading with two of these mistakes. Run it:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Missing Font</title>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400&display=swap" rel="stylesheet">
  <style>
    h2 { font-family: "Poppin"; font-weight: 700; }
  </style>
</head>
<body>
  <h2>Sangeet Night</h2>
</body>
</html>

And here is the fix: the correct name, the 700 weight added to the link, and a fallback list:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Font Fixed</title>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
  <style>
    h2 { font-family: "Poppins", Arial, sans-serif; font-weight: 700; }
  </style>
</head>
<body>
  <h2>Sangeet Night</h2>
</body>
</html>

Practice Task: A Farewell Party Invitation

Your class is organising a farewell party for the final year students, and you are making the invitation page. Complete the four TODO steps.

  • Load exactly two Google Fonts with one <link> tag
  • Use the heading font for h2 and the body font for body, each with a fallback and a generic family
  • Set a comfortable line-height for the text
  • Style the small label with uppercase letters and letter-spacing
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Farewell Party</title>
  <!-- TODO 1: Add a Google Fonts link for one heading font and one body font -->
  <style>
    body {
      /* TODO 2: Use your body font with a fallback, size 17px, line-height 1.7 */
    }
    h2 {
      /* TODO 3: Use your heading font with a fallback */
    }
    .label {
      /* TODO 4: Make it uppercase, 13px, with letter-spacing 0.15em */
    }
  </style>
</head>
<body>
  <p class="label">Final Year B.Sc. presents</p>
  <h2>Farewell Party 2026</h2>
  <p>Join us for music, food and one last group photo before we all go our own ways.</p>
  <p>Saturday, 5 PM, College Auditorium</p>
</body>
</html>
Show one possible answer (try it yourself first!)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Farewell Party</title>
  <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Poppins:wght@400;600&display=swap" rel="stylesheet">
  <style>
    body {
      font-family: "Poppins", system-ui, sans-serif;
      font-size: 17px;
      line-height: 1.7;
      text-align: center;
    }
    h2 {
      font-family: "Playfair Display", Georgia, serif;
      font-size: 38px;
      line-height: 1.2;
    }
    .label {
      text-transform: uppercase;
      font-size: 13px;
      font-weight: 600;
      letter-spacing: 0.15em;
    }
  </style>
</head>
<body>
  <p class="label">Final Year B.Sc. presents</p>
  <h2>Farewell Party 2026</h2>
  <p>Join us for music, food and one last group photo before we all go our own ways.</p>
  <p>Saturday, 5 PM, College Auditorium</p>
</body>
</html>

Key Takeaways

  • font-family takes a list of fonts. The browser uses the first one available, so always end with a generic family like sans-serif or serif.
  • A system font stack (system-ui, sans-serif) is fast and needs no download.
  • Google Fonts are free: add the <link> in the head, then use the name in CSS. They load from the internet, so fallbacks matter.
  • Load only the weights you use, and choose a proper font for Hindi and other Indian scripts.
  • Use unitless line-height around 1.5 to 1.8 for paragraphs and small letter-spacing only for short uppercase labels.
  • Two fonts per page is usually enough.

❓ Frequently Asked Questions

Yes. Fonts on Google Fonts are released under open licences, so you can use them on personal and commercial websites without paying.
Google Fonts are downloaded from the internet each time a page needs them. When there is no connection, the browser uses the next font in your font-family list.
Put quotes around font names that contain spaces, like "Playfair Display". Quotes are optional for one-word names. Never put quotes around generic families such as serif or sans-serif.
There is no difference: bold is the same as 700 and normal is the same as 400. Numbers give you more choices, like 300 for light or 600 for semi bold.
Yes. You can download the font files and load them with the @font-face rule. This works offline, but the link method is simpler for beginners.
Was this lesson helpful?

🎯 Finished this lesson?

🔗 Related Tutorials
🤖 Got a Doubt? Ask AI
Get instant answers in Hindi or English
🤖
Z2T Bot
Online
Ask me anything about this tutorial — I'm here! 👋