One place for hosting & domains

      How To Load and Use Custom Fonts with CSS


      The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      The visual identity of a website is largely dictated by two principles of design: color and typeface. In the last decade, there have been great strides in providing custom fonts to users with more preloaded fonts on devices, the ability to load custom fonts with the @font-face rule, and the use of font hosting services. Web browsers have also implemented support for variable fonts, which are single font files from which multiple fonts can be interpolated, providing a high-degree of tuning and font customization.

      In this tutorial, you will try out examples of loading fonts onto your website. You will use the font stack, a rank ordering of fonts based on availability, to use fonts that may be installed on the user’s device. Then, you will use a font-hosting service, Google Fonts, to find, select, and load custom fonts onto your page. Lastly, you will load a self-hosted font family using the @font-face rule, followed by a self-hosted variable font.

      Prerequisites

      • An understanding of CSS’s cascade and specificity features, which you can get by reading How To Apply CSS Styles to HTML with Cascade and Specificity.
      • Knowledge of type selectors, combinator selectors, and selector groups, which you can find in How To Select HTML Elements to Style with CSS.
      • An understanding of font stacks and font properties in CSS, which you can find in the tutorial How To Style Text Elements with Font, Size, and Color in CSS.
      • An empty HTML file saved on your local machine as index.html that you can access from your text editor and web browser of choice. To get started, check out our How To Set Up Your HTML Project tutorial, and follow How To Use and Understand HTML Elements for instructions on how to view your HTML in your browser. If you’re new to HTML, try out the whole How To Build a Website with HTML series.

      Setting Up the HTML and Creating the Initial Font Stack

      The concept of a font stack comes from early in the web, when there were only a few trustworthy fonts that one could installed on the majority of computers. It was often likely the font would not be available, so the font stack provided an order of fonts that the browser could attempt to find and load. In this section, you will learn the principles of a resilient font stack and what options are available for fonts on modern devices. But first, you will create example HTML to demonstrate the fonts.

      Begin by opening index.html in your text editor. Then, add the following HTML to the file:

      index.html

      <!doctype html>
      <html>
        <head>
          <meta charset="utf-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <title>A Demo Font Family Page</title>
          <link href="https://www.digitalocean.com/community/tutorials/styles.css" rel="stylesheet" />
        </head>
        <body>
        </body>
      </html>
      

      Inside the <head> tag, the first <meta> tag defines the character set for the HTML file. The second <meta> tag defines how mobile devices should render the page. Next, the <title> tag gives the page its title. Finally, the <link> tag references the CSS file you will use later to create the styles for the page.

      Next, inside the <body> tag, add the content of the page. This content is known as filler content from Cupcake Ipsum and it provides text to appear like content without actually saying anything. The filler content is highlighted in the following code block. You will encounter this highlighting method throughout the tutorial as code is added and changed:

      index.html

      <!doctype html>
      <html>
        <head>
          <meta charset="utf-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <title>A Demo Font Family Page</title>
          <link href="https://www.digitalocean.com/community/tutorials/styles.css" rel="stylesheet" />
        </head>
        <body>
          <main>
            <header>
              <div class="content-width">
                <h1>Sweet strawberry cheesecake</h1>
                <p><em>Sweet muffin bear claw</em> donut chupa chups liquorice tiramisu candy canes sweet.</p>
              </div>
            </header>
      
            <div class="content-width">
              <p>Chocolate shortbread caramels tootsie roll tiramisu sweet dessert apple pie fruitcake. <strong>Croissant icing chupa chups</strong> sweet roll cake tart fruitcake soufflé jujubes. Shortbread brownie tootsie roll ice cream pudding dessert marshmallow sesame snaps. Cake pie jujubes lemon drops sesame snaps soufflé cookie jujubes wafer. Caramels ice cream fruitcake pastry cheesecake chocolate tootsie roll cake marshmallow. Pie candy canes cupcake dragée bonbon fruitcake marzipan. Tootsie roll halvah bonbon cake muffin gummies. Bonbon cotton candy marzipan cake sesame snaps chupa chups donut dessert. Macaroon gummies macaroon biscuit chocolate carrot cake gummi bears.</p>
      
              <h2>Donut candy canes cotton candy</h2>
      
              <p><strong><em>Liquorice gingerbread tiramisu</em></strong> pie bonbon soufflé. Jujubes tootsie roll muffin gingerbread powder. Carrot cake halvah chocolate bar tart sugar plum sugar plum pastry. Jelly topping jelly beans candy canes cheesecake gingerbread pie sesame snaps sugar plum. Pie cheesecake pudding jelly brownie jelly beans halvah. Ice cream powder carrot cake bear claw cake cheesecake.</p>
      
              <p><em>Jelly-o jelly-o jelly</em> lollipop croissant. Carrot cake tart danish macaroon dragée gingerbread. Sugar plum cotton candy biscuit <strong>fruitcake powder liquorice</strong>. Shortbread candy pie tart pudding. Sesame snaps bear claw tart tiramisu donut chocolate cake. Cheesecake tiramisu chocolate cake dessert dessert candy candy canes apple pie marshmallow. Sweet croissant pudding toffee tootsie roll gummies tart pastry pie. Candy apple pie cake wafer tootsie roll tart icing halvah.</p>
      
              <h3>Gingerbread gummi bears</h3>
      
              <p><em>Tiramisu sweet pastry</em> danish topping ice cream caramels. Tiramisu candy liquorice jelly-o marzipan candy canes cupcake topping. Gummi bears jujubes carrot cake shortbread sesame snaps marshmallow danish pudding cotton candy. <strong>Cake jujubes biscuit</strong> topping marzipan sweet roll apple pie bonbon. Bear claw donut bear claw bonbon caramels halvah gummi bears. Gummi bears apple pie jelly-o donut sesame snaps icing marzipan.</p>
      
              <p><strong><em>Bonbon chupa chups</em></strong> donut dessert pudding. Sweet roll caramels dessert muffin croissant. Powder chocolate lollipop ice cream bonbon pie candy muffin cotton candy. Fruitcake topping chupa chups toffee jelly-o halvah. Candy soufflé toffee gummies fruitcake oat cake chocolate cake. Dessert cupcake cheesecake sweet roll bear claw. Marshmallow halvah bear claw biscuit dragée marzipan lemon drops jelly.</p>
            </div>
          </main>
        </body>
      </html>
      

      The filler content contains a number of elements that are used to provide different font styles. The <strong> tag will by default make its content bold, the <em> tag will italicize its content, and the heading tags will increase the font size and bold their content.

      Next, return to your text editor and create the styles.css file in the same folder as index.html. This is the file that you referenced in the <head> element of index.html. In the styles.css file, add the following code:

      styles.css

      body {
        margin: 0;
        background-color: hsl(0, 0%, 100%);
        color: hsl(0, 0%, 10%);
        line-height: 1.5;
      }
      
      .content-width {
        max-width: 70ch;
        width: calc(100% - 4rem);
        margin: 0 auto;
      }
      
      main {
        margin-bottom: 4rem;
      }
      
      header {
        margin-bottom: 4rem;
        padding: 2rem 0;
        background-color: hsl(280, 50%, 40%);
        border-bottom: 4px solid hsl(300, 50%, 50%);
        color: hsl(300, 50%, 90%);
      }
      
      header p {
        color: hsl(300, 50%, 85%);
      }
      
      h1, h2, h3 {
        margin: 0;
        line-height: 1.25;
      }
      
      h2, h3 {
        color: hsl(280, 50%, 40%)
      }
      

      These styles create the overall visual style of the page. The header has a purple background with the h1 and p inside being a light purple. The main and .content-width selectors create the layout of the page, and the body and heading selectors provide several typographic styles by setting the line-height, color, and margin values.

      Save your changes to styles.css, then open your web browser. Open index.html in the browser by dragging the file into the browser window, or using the browser’s Open File option. The browser will render the HTML and CSS code to produce a page like the following image:

      Large purple block with white text in a serif font inside. Below there are several paragraphs of serif text in a dark gray with purple bold serif headings.

      The text of the index.html file in your browser will be using the browser’s local default font. In most cases, this will be a serif font like Times New Roman. The most performant way to customize fonts is to use fonts already on the end user’s computer. Using local fonts relieves the browser of downloading and processing sizable files.

      Today, there are often several dozen local fonts to choose from; these are known as system fonts. Both Microsoft and Apple keep an updated list of the fonts that come with their systems.

      To begin using pre-installed system fonts, return to styles.css in your text editor. In the body selector, add a font-family property, and make its value a comma-separated list of fonts known as a font stack:

      styles.css

      body {
        margin: 0;
        background-color: hsl(0, 0%, 100%);
        color: hsl(0, 0%, 10%);
        line-height: 1.5;
        font-family: "PT Sans", Calibri, Tahoma, sans-serif;
      }
      ...
      

      The browser will sequentially attempt to load the local fonts in the font stack until it is successful. For this font stack, the first font to attempt is "PT Sans", which is in quotes because it is a multi-word font name. PT Sans is a font from ParaType that comes pre-installed on Apple operating systems and is also available for free from Google Fonts. The next font is Calibri, followed by another comma and Tahoma. Calibri is a font from Microsoft that comes installed on recent version of Windows, and Tahoma is another font from Microsoft that has been present on Apple operating systems for over a decade.

      The final font is the generic name-spaced value sans-serif. If none of the previous three fonts are available, then the browser will use the browser’s default sans-serif font, such as Helvetica or Arial.

      Save your changes to styles.css and then refresh index.html in your browser. Your operating system and installed fonts will determine which font is rendered and how it is rendered. The following image shows how PT Sans appears as the font when loaded in Firefox on macOS:

      Large purple block with white text in a sans-serif font inside. Below are several paragraphs of sans-serif text in a dark gray with purple bold sans-serif headings.

      A font family consists of all the weight and style variations of a given font. Families can include many additional weight and styles that change how thin, thick, and slanted a font will display.

      The font-style property determines the slant of the font. The value is most commonly italic; however, some fonts support the oblique value, which accepts an optional degree value to indicate the steepness of the slant.

      The font-weight property has two defined named values of normal and bold, but the most versatile and predictable manner to determine this value is to use a weight number. The weight number values are commonly defined in increments of 100 from 100 to 900, with 100 being a thin weight and 900 being a thick weight. If the browser cannot find a font corresponding to the specified weight, it will find the closest available size.

      To set some new base font styling for this page throughout the tutorial, return to styles.css in your text editor. Then create an element selector for each of the h1, h2, h3, and p elements. Inside each selector, add the highlighted CSS from the following code block to increase the font size and emphasize the headings:

      styles.css

      ...
      h2, h3 {
        color: hsl(280, 50%, 40%)
      }
      
      h1 {
        font-size: 3rem;
        font-weight: 100;
      }
      
      h2 {
        font-size: 2rem;
        font-weight: 200;
      }
      
      h3 {
        font-size: 1.75rem;
        font-style: italic;
        font-weight: 200;
      }
      
      p {
        font-size: 1.125rem;
      }
      

      The h1 here is set to a font-size of 3rem, which is equivalent to 48px, with a thin font-weight of 100. Then, the h2 is set to 2rem, equivalent to 32px, and a font-weight of 200. Next, the h3 is set to the same font-weight and a slightly smaller font-size as the h2, but gains an added font-style property set to italic. Lastly, the p element selector bumps up the standard font-size to 1.125rem, which is equal to 18px in this case. The adjustments to the overall styling of this text will remain the same as you change the font used in each section.

      Save the changes to styles.css, then return to your browser and refresh index.html. The overall text size has bumped up, with the heading styles gaining more distinction from one another. The following image shows how this will appear in the browser:

      Large purple block with white text in a sans-serif font inside. Below are several paragraphs of sans-serif text in a dark gray with purple thing sans-serif headings. The font sizing has increased overall.

      In this section, you used the font stack to load a series of possible fonts on the page in a ranked order. You also learned about the possible variations of a font family with the font-weight and font-style properties. In the next section, you will use a font from a font hosting service.

      Finding and Loading a Font File from a Hosted Service

      Hosted font services are a popular and effective way of finding and providing custom fonts to a websites. Services such as Google Fonts, Adobe Fonts (formerly Typekit), and Typography.com provide a large library of high-quality fonts that a client will temporarily download when viewing your page. This means that you no longer have to worry about which fonts are on the client’s system.

      Each font hosting service has its own process for loading fonts, and in many cases there is an associated cost. For this section, you will find and load fonts from Google’s service, as it hosts open-source and limited license fonts free of charge.

      To begin, open fonts.google.com. Search for the font named “Open Sans” using the search bar at the top of the page. The search results will list the matching term, which is a link taking you to the Google Fonts Open Sans page. On this page, there is a list of several font styles. Each one of these font weight and style combinations is a unique font file that the browser will download.

      Note: Each font-weight and font-style will need to be selected based on need, instead of selecting them all. More fonts selected means more fonts need to be downloaded, thus increasing the website load time. It is important to only load the font weights and styles that are used in your design.

      For this design, select Light 300, Light 300 italic, Regular 400, Regular 400 italic, Bold 700, and Bold 700 italic. The following image displays how this selection will look in Google Fonts:

      View of the Google Fonts interface with a listing of font weights and styles on the left. On the right is a listing of selected fonts weights and styles with code text below.

      Next, copy the <link> tags necessary to load the files from the Google Fonts service. To do that, select the <link> option instead of the @import option as the way to load the files in the Google Fonts interface. Copy the series of <link> tags presented. Then, return to index.html in your text editor. Go inside the <head> element and, after the <link> tag loading styles.css, paste the <link> tags from Google Fonts. The highlighted HTML in the following code block demonstrates where to add the copied code:

      index.html

      <!doctype html>
      <html>
        <head>
          ...
          <link href="https://www.digitalocean.com/community/tutorials/styles.css" rel="stylesheet" />
          <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=Open+Sans:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap" rel="stylesheet">
        </head>
        <body>
          ...
        </body>
      </html>
      

      The first two <link> elements perform a task called a preconnect, which tells the browser to prioritize an external web connection. In turn, these two <link> elements prepare the browser to load the CSS file and font files from the third <link> as soon as possible.

      Now that the font is ready for the browser to load it on to the page, next you need to apply the font styling so the text is rendered with that font.

      Save your changes to index.html, then return to styles.css in your text editor. In your body selector, go to the font-family property. Prepend the value with the font name "Open Sans" in quotes before the "PT Sans" font, followed by a comma. The highlighted CSS in the following code block shows where the new font is placed in the font stack:

      styles.css

      body {
        margin: 0;
        background-color: hsl(0, 0%, 100%);
        color: hsl(0, 0%, 10%);
        line-height: 1.5;
        font-family: "Open Sans", "PT Sans", Calibri, Tahoma, sans-serif;
      }
      ...
      

      By adding Open Sans to the beginning of the font stack, the browser will fallback to the next available local font if the browser is unable to load the files from Google. It is important to always have a font stack of at least two, with the last font in the stack being sans-serif, serif, monospace, or another named value that most effectively resembles the intended font.

      Save your changes to styles.css and open index.html in the web browser. The text on the page will now render using the Open Sans font loaded from Google Fonts. The text with a font-weight set to 100 and 200 will instead use 300 since that is the closest available. The following image illustrates how this will appear in the browser:

      Large purple block with white text in a sans-serif font inside. Below are several paragraphs of sans-serif text in a dark gray with purple thin sans-serif headings.

      In this section, you loaded a font family from Google Fonts. You learned how each font weight and style is a different file loaded from the service, and that the number of loaded variations can impact site performance. In the next section, you will load the fonts by writing your own @font-face rule to populate self-hosted font files.

      Loading a Self-Hosted Font with @font-face

      Self-hosted fonts are font files that are stored on your server alongside the other web components, such as HTML and CSS files. A common reason to consider self-hosting your font files is when you want to use a font that is not provided by a hosting service. When self-hosting, there is more control over how the fonts relate to one another and what they are named, which you can set via the definitions of the @font-face rules. In this section, you will write your own @font-face rules and load a family of fonts onto your web page.

      For this section, you will need to download the example zip file containing open-source fonts. You can download this through your browser or use the following curl command:

      • curl -sL https://assets.digitalocean.com/articles/68060/fonts.zip -o fonts.zip

      Once you have downloaded the file, extract the fonts directory contained in the zip file and place it in the same directory as the index.html and styles.css file on your computer. On Linux, you can do this from the command line with the following unzip command:

      Next, open up index.html in your text editor. Since you will be loading a local font from the zip file, you can remove the Google Font code. In this section, you will be loading the font files from your existing styles.css file. Make sure the contents of your <head> element are set up like the following code block:

      index.html

      <!doctype html>
      <html>
        <head>
          <meta charset="utf-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <title>A Demo Font Family Page</title>
          <link href="https://www.digitalocean.com/community/tutorials/styles.css" rel="stylesheet" />
        </head>
        <body>
          ...
        </body>
      </html>
      

      Save your edits to index.html, then open styles.css in your text editor.

      You can use the @font-face rule to load a custom font on a web page. The history of loading custom fonts has lead to a compound method to support the widest number of browsers. Unlike other at-rules, like @media or @supports, the @font-face rule has no additional arguments. Inside the rule block, only a set number of properties are accepted. The most important is font-family, which describes the name the browser will use to reference and load the appropriate font files. Then, the src property references the location of the font files. In order to support versions of Internet Explorer prior to version 9, two src properties are necessary, with the first only referencing the .eot font file format. The second src property will then be a comma separated list of font file formats. The browser version will select the appropriate format that it supports.

      To begin using the @font-face rule, open styles.css in your text editor. At the top of the file, before the body selector, create the following @font-face rule:

      styles.css

      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-Regular.eot');
        src: url('fonts/fira/eot/FiraSans-Regular.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-Regular.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-Regular.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-Regular.ttf') format('truetype');
      }
      
      body {
        ...
      }
      ...
      

      Inside this rule, you’ve added a font-family property with a value of "Fira Sans" in quotes. Since this code is defining an overall font-family, only one font name should be used. The comma separated list of font formats for src is two parted. The first is the url() that, like a background-image property, provides the path to the file format on the server. Then, the format() explains what type of file is being referenced, allowing the browser to select the supported format.

      The fira folder inside the fonts folder contains four folders with specific file formats of the Fira Sans font. EOT stands for Encapsulated OpenType, a format Microsoft developed for Internet Explorer to load custom fonts. TTF stands for TrueType Font, and is an older font format that wasn’t originally developed for the web. The WOFF and WOFF2 formats stand for Web Open Font Format, with the “2” signifying the second version of the format. The majority of modern browsers support TTF, WOFF, and WOFF2 equally. To create an @font-face rule that covers the most possible browser formats, you provided multiple sources for your font. The EOT is referenced in both src properties because version 9 and later of Internet Explorer use the comma-separated format instead.

      Now that you have the @font-face rule for Fira Sans created, go to the font-family property in the body selector. In the value for the font-family, replace "Open Sans" with "Fira Sans" to use the self-hosted font on your page. The highlighted portion of the following code block demonstrates this change:

      styles.css

      @font-face {
        ...
      }
      
      body {
        margin: 0;
        background-color: hsl(0, 0%, 100%);
        color: hsl(0, 0%, 10%);
        line-height: 1.5;
        font-family: "Fira Sans", "PT Sans", Calibri, Tahoma, sans-serif;
      }
      ...
      

      Even though the fonts are being loaded from the same place as the styles.css and index.html file, it is important to keep a font-stack of alternates. There are numerous unknown reasons a self-hosted font may not load, and if the browser runs into an issue, a sufficient backup helps to maintain a similar aesthetic for your site.

      Save your changes to styles.css and open index.html in a web browser. Notice that the bold and italics versions of the font do not look quite right. This is because in the @font-face rule only the regular font weight and style files were loaded and used. When the browser needs to apply a bold weight or italic style to a font, but lacks the appropriate font file, the browser creates the needed variation. This altered form of a font is known as a faux bold and faux italic. Faux bold is created by adding a stroke to the font, which often creates a wider spacing between characters that could interfere with your intended layout. Faux italic is created by slanting the font, which often does not use space as well as a true italic would.

      The following image shows how the faux bold, italic, and bold italic styles appear in the browser:

      Three lines of text, the first with a generated bold style, the second with a generated italic style, and the last with a generated bold italic style.

      In order to provide the browser with the appropriate variations of a font family, more details need to be provided in the @font-face rule, and you need to create more rules to load additional variation files.

      Return to styles.css in your text editor. In the @font-face rule, add a font-weight and a font-style property after the second src property:

      styles.css

      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-Regular.eot');
        src: url('fonts/fira/eot/FiraSans-Regular.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-Regular.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-Regular.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-Regular.ttf') format('truetype');
        font-weight: normal;
        font-style: normal;
      }
      ...
      

      Here you set the value for both properties to normal. For the font-weight, the normal value is equivalent to the 400 numerical weight value. These properties tell the browser to apply these font files for normal variations. Thus the FiraSans-Regular font file will be used when the text needs to be a normal weight and style.

      Next, to provide the variations needed to correct the faux bold and faux italic, add more @font-face rules to reference each font-weight and font-style combination:

      styles.css

      /* Fira Sans Regular */
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-Regular.eot');
        src: url('fonts/fira/eot/FiraSans-Regular.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-Regular.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-Regular.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-Regular.ttf') format('truetype');
        font-weight: normal;
        font-style: normal;
      }
      
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-Italic.eot');
        src: url('fonts/fira/eot/FiraSans-Italic.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-Italic.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-Italic.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-Italic.ttf') format('truetype');
        font-weight: normal;
        font-style: italic;
      }
      
      /* Fira Sans Bold */
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-Bold.eot');
        src: url('fonts/fira/eot/FiraSans-Bold.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-Bold.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-Bold.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-Bold.ttf') format('truetype');
        font-weight: bold;
        font-style: normal;
      }
      
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-BoldItalic.eot');
        src: url('fonts/fira/eot/FiraSans-BoldItalic.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-BoldItalic.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-BoldItalic.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-BoldItalic.ttf') format('truetype');
        font-weight: 700;
        font-style: italic;
      }
      ...
      

      As more variations are added, it is helpful to add comments to more easily identify the group of font weights. You therefore added a CSS comment above the first @font-face rule. Then, below the first rule, you created three more @font-face rules for the italic, bold, and bold italic variations of the font.

      Save these updates to your styles.css file, then refresh index.html in the browser. Your browser is now loading all the variations of the font family provided. The following image showcases the differences between the faux and true versions of bold, italic, and bold italic:

      A comparison of text with a list of browser generated bold, italic, and bold italic styles on the left and the true font styles on the right.

      The true bold is much thicker than the browser’s faux bold, and the text is closer together, accounting for the thicker font strokes. The true italic is more notable when comparing the lowercase a character in the word “Italic.” The font changes the style of the a character when italic. Additionally, the slant of the true italic is a lesser degree than the browser’s faux italic.

      Next, there are a few more font variations to load, since the heading elements use thinner weight versions of Fira Sans.

      Return to styles.css in your text editor and create four more @font-face rules above the regular version @font-face rule:

      styles.css

      /* Fira Sans Thin */
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-Thin.eot');
        src: url('fonts/fira/eot/FiraSans-Thin.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-Thin.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-Thin.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-Thin.ttf') format('truetype');
        font-weight: 100;
        font-style: normal;
      }
      
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-ThinItalic.eot');
        src: url('fonts/fira/eot/FiraSans-ThinItalic.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-ThinItalic.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-ThinItalic.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-ThinItalic.ttf') format('truetype');
        font-weight: 100;
        font-style: italic;
      }
      
      /* Fira Sans Light */
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-Light.eot');
        src: url('fonts/fira/eot/FiraSans-Light.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-Light.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-Light.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-Light.ttf') format('truetype');
        font-weight: 200;
        font-style: normal;
      }
      
      @font-face {
        font-family: "Fira Sans";
        src: url('fonts/fira/eot/FiraSans-LightItalic.eot');
        src: url('fonts/fira/eot/FiraSans-LightItalic.eot') format('embedded-opentype'),
             url('fonts/fira/woff2/FiraSans-LightItalic.woff2') format('woff2'),
             url('fonts/fira/woff/FiraSans-LightItalic.woff') format('woff'),
             url('fonts/fira/woff2/FiraSans-LightItalic.ttf') format('truetype');
        font-weight: 200;
        font-style: italic;
      }
      ...
      

      These new rules load the Thin and the Light variations of Fira Sans, mapped to the 100 and 200 font-weight values, respectively. Since there are not word values for these sizes, you changed the values for the regular and bold font-weight properties to their numerical values.

      Save these changes to styles.css, then return to your browser and refresh index.html. The heading elements are now using the thinner variants of Fira Sans, as shown in the following image:

      Large purple block with white text in a sans-serif font inside. Below are several paragraphs of sans-serif text in a dark gray with purple thin sans-serif headings.

      In this section, you loaded self-hosted font files with @font-face rules. You learned how faux bold and italic can impact the visual presentation of a font and how to link many font files together with a common font-family value. In the last section, you will use a variable font, which allows for many variations sourced from a single font file.

      Working with Variable Fonts

      Variable fonts are a relatively new addition to the options of web typography. Where in the previous section each font weight and style had to be loaded from an individual file, variable fonts contain information in a single file from which many variations can be calculated. Variable fonts can increase performance, as well as providing much more design possibilities than before. In this section, you will load a variable font using the @font-face rule and tweak the display of the font to find the right variation.

      To begin working with variable font, open styles.css in your text editor. First, remove all the @font-face rules from the previous section and replace them with the following new rule:

      styles.css

      @font-face {
        font-family: Raleway;
        src: url('fonts/raleway/Raleway.woff2') format('woff2');
        font-style: normal;
        font-weight: 300 800;
      }
      
      body {
      ...
      

      A variable font structurally looks the same as a standard @font-face rule. You first declare a font-family name, then supply a list of src values, although often with variable fonts only one format is necessary. The font-style property was set to normal for this font. A difference comes with the font-weight value. Instead of defining a single value, a range is written with the thinnest weight followed by the thickest weight. By defining this range, the browser can prepare for the possible variation calculations that will occur. Here you set the font-face rule for Raleway, with a font-weight range from 300 to 400.

      Next, you will need to establish Raleway in the font stack. Remove "Fira Sans" from the beginning of the font stack and replace it with Raleway. Since the name Raleway does not contain any spaces, it does not need to be in quotes:

      styles.css

      ...
      body {
        margin: 0;
        background-color: hsl(0, 0%, 100%);
        color: hsl(0, 0%, 10%);
        line-height: 1.5;
        font-family: Raleway, "PT Sans", Calibri, Tahoma, sans-serif;
      }
      ...
      

      Save your changes to styles.css and open index.html in your web browser. The browser produces true font weights instead of faux weights, but is not treating italics correctly due to a lack of defined italic style.

      To set up the italic version of the Raleway variable font, return to styles.css in your text editor. Below the first @font-face rule, create a new rule set:

      styles.css

      @font-face {
        font-family: Raleway;
        src: url('fonts/raleway/Raleway.woff2') format('woff2');
        font-weight: 300 800;
        font-style: normal;
      }
      
      @font-face {
        font-family: Raleway;
        src: url('fonts/raleway/Raleway-Italic.woff2') format('woff2');
        font-weight: 300 800;
        font-style: italic;
      }
      
      body {
        ...
      }
      ...
      

      The src has changed its font file name from Raleway.woff2 to Raleway-Italic.woff2, and the font-style value is now italic.

      Save your changes to styles.css and refresh the page in your browser. The browser is now rendering the italic version of the various weights of Raleway. The following image shows the updated version of the page with a full Raleway variable font set:

      Large purple block with white text in a sans-serif font inside. Below are several paragraphs of sans-serif text in a dark gray with purple thin sans-serif headings.

      The advantage of using variable fonts is that any whole numerical value defined in the font-weight range is available. While standard font weights increment by values of 100, variable fonts weights can increment by values as low as 1. This provides a method to fine-tune the visual design of the font in ways not possible before.

      To use the weight values from the range, return to styles.css in your text editor and make the following changes:

      styles.css

      ...
      h1 {
        font-size: 3rem;
        font-weight: 350;
      }
      
      h2 {
        font-size: 2rem;
        font-weight: 570;
      }
      
      h3 {
        font-size: 1.75rem;
        font-style: italic;
        font-weight: 450;
      }
      
      p {
        font-size: 1.125rem;
      }
      
      strong {
        font-weight: 600;
      }
      

      For the h1 selector, you changed the font-weight value to 350. Then, you set the h2 font-weight property to 570 and the h3 to 450. Lastly, you created a strong element select with a font-weight property set to 650.

      Be sure to save your changes to styles.css, then return to your browser and refresh index.html. The browser now renders various weights of the Raleway font throughout the page. The following image shows how this appears in the browser:

      Large purple block with white text in a sans-serif font inside. Below are several paragraphs of sans-serif text in a dark gray with purple bold sans-serif headings.

      In this final section, you loaded and used a variable font on your web page. Much more variation can come from one or two variable fonts than a dozen standard fonts. You also learned how to adjust a variable font to find the right variation for your design needs to a degree unlike before.

      Conclusion

      Fonts are a key component to the visual aesthetic of a design. They are highly sought after assets that help one website standout from another.

      Throughout this tutorial, you learned the main ways fonts can be used on a website. You used local fonts and a font stack to tell the browser which fonts to try loading. Then, you used a font hosting service to effectively load the font Open Sans from Google Fonts. Next, you set up your own series of @font-face rules and created your own family of self-hosted fonts. Lastly, you built on what you learned loading your own fonts to use variable font and try out the versatility and performance they provide. Remember that it is important to always have fallback fonts in the font stack regardless if the font is local, from a hosting service, or self-hosted, because the font may not load for unknown reasons.

      If you would like to read more CSS tutorials, try out the other tutorials in the How To Style HTML with CSS series.



      Source link

      How To Use the Display Property to Manipulate the Box Model in CSS


      The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      HTML and CSS work together to render visual elements of a web page in the browser. HTML elements carry computational and hierarchical meaning and have default styles the browsers apply to these elements. Among these default styles is the display property. The value of this property affects the box model, the mechanism that determines how elements interact with one another on a page. Using the display property, you can efficiently control how an element interacts with the layout of your web page, allowing you to create more flexible solutions for situations like responsive mobile web design.

      In this tutorial, you will work through multiple demos using the display property and learn how it determines flow interactions with other elements. You will begin with the foundational values of display: block and inline. You will then use the combination value of inline-block to learn about the possibilities of the inline- prefixed values. Next, you will learn about the power and danger of using the none value. Lastly, you will use a max-width media query to transform a table into a display: block view on a small screen.

      Prerequisites

      Setting Up the Initial HTML and CSS files

      To begin, you will set up the HTML and CSS files that you will use throughout the tutorial. You will also explore the default display values of text-containing elements.

      Start by opening index.html in your text editor and adding the following code to your file:

      index.html

      <!doctype html>
      <html>
        <head>
          <meta charset="utf-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <title>The Terrestrial Planets</title>
          <link href="https://www.digitalocean.com/community/tutorials/styles.css" rel="stylesheet" />
        </head>
        <body>
        </body>
      </html>
      

      This code sets up the framework necessary for every HTML document. The information contained in the <head> element defines the page’s name in the <title> element and where to load the stylesheet, which is determined in the <link> element. The <meta> tags define the character encoding and small screen device handling, respectively. The main content of the page will be added inside the <body> tags throughout the tutorial.

      Next, inside the <body> element, create a <main> element with a class attribute set to content-width. You will use this element to handle the layout of the content within the page. Inside the <main> element, create an <h1> tag pair followed by a <p>. Within the <h1> and <p> elements, add the content shown in the following code block:

      index.html

      <!doctype html>
      <html>
        <head>
          ...
        </head>
        <body>
          <main class="content-width">
            <h1>The Terrestrial Planets of the Solar System</h1>
      
            <p>
              The four inner planets of the Solar System consist of Mercury, Venus, Earth, and Mars. These planets are known as terrestrial due to their hard, rocky surface. Compared to the gaseous planets of the outer solar system, the inner terrestrial planets are significantly smaller in size. Depending on tectonic activity and presence of liquids these planets will have features such as canyons, mountains, and volcanoes on their surface.
            </p>
          </main>
        </body>
      </html>
      

      Highlighted code, like that in the previous code block, is used throughout this tutorial to emphasize changes to the code.

      Save your changes to index.html, then create a new file called styles.css and open it in your editor as well.

      In your styles.css file, you will add selectors for the elements you created in index.html. Create a selector for body and .content-width, then add the styling properties as demonstrated in the following code block:

      styles.css

      body {
        margin: 0;
        font-family: sans-serif;
        line-height: 1.5;
        color: hsl(215, 5%, 20%);
        background-color: hsl(215, 5%, 98%);
      }
      
      .content-width {
        margin: 2rem auto;
        width: 90%;
        max-width: 40rem;
      }
      

      The styles for the body element reset some default layout and text styling with the margin, font-family, and line-height properties. The color and background color add a dark-gray blue and a light-gray blue to the page. The .content-width properties will keep it centered to the page, taking up 90% of the screen width until it reaches a maximum size of 40rem, or 640px.

      Next, add some font styling to make the text more legible:

      styles.css

      ...
      .content-width {
        margin: 2rem auto;
        width: 90%;
        max-width: 40rem;
      }
      
      h1 {
        font-size: 2rem;
        font-weight: 400;
        line-height: 1.2;
      }
      
      p {
        font-size: 1.125rem;
      }
      

      The h1 properties define the size and weight of the text and bring the line-height property down to a better spacing for headings. Lastly, the p element selector bumps up the font-size to 1.125rem, or 18px.

      Save your changes to styles.css, then open your web browser. Open index.html in the browser by dragging the file into the browser window or using the browser’s Open File option. The browser will render the HTML and CSS code to produce a page like the following image:

      Large header text and smaller paragraph text in a dark blue-gray color on a light gray background.

      So far, the HTML elements that you have worked with are known as block elements. These are elements that create defined areas of content that take up the full width of the parent container. Additionally, block elements are usually rendered by themselves on a new line. This means that added block elements stack toward the end of the page. For a top-to-bottom, left-to-right language like English, block elements stack toward the bottom of the browser window.

      Next, you will add inline elements, which are elements that exist within the flow of text content. Since inline elements do not take up the entire width of their parent, and since they are not rendered on their own lines, they are added in the direction of the text flow. For English, this is a left-to-right direction.

      Where block elements define the meaning and group of content, like a paragraph, inline elements provide context about a word or group of words, such as an emphasis.

      Return to index.html in your text editor. In the second sentence, wrap the word terrestrial in the emphasis tag, <em>. Then, in the third sentence, wrap the phrase gaseous planets in an anchor tag, <a>. In the opening <a> tag add an href attribute with a value of https://en.wikipedia.org/wiki/Giant_planet. This will link to the Wikipedia page on the topic. The highlighted HTML in the following code block demonstrates how this is set up:

      index.html

      ...
      <p>
        The four inner planets of the Solar System consist of Mercury, Venus, Earth, and Mars. These planets are known as <em>terrestrial</em> due to their hard, rocky surface. Compared to the <a href="https://en.wikipedia.org/wiki/Giant_planet">gaseous planets</a> of the outer solar system, the inner terrestrial planets are significantly smaller in size. Depending on tectonic activity and presence of liquids these planets will have features such as canyons, mountains, and volcanoes on their surface.
      </p>
      ...
      

      Save these additions to index.html then, return to styles.css in your text editor. To demonstrate the difference between block and inline elements, create an a element selector. Inside the selector add the display property set to block, as demonstrated in the following code block:

      styles.css

      ...
      p {
        font-size: 1.125rem;
      }
      
      a {
        display: block;
      }
      

      Save your change to styles.css, then return to the page in your web browser. Refresh the page to load the latest version of your code. The page demonstrates the key difference between a block and an inline element, as the link set to display: block now occupies its own line. This is demonstrated in the following image:

      Large header text and smaller paragraph text in a dark blue-gray color on a light gray background with a blue underlined text breaking up the paragraph into two sections.

      The primary difference between a block and an inline value is that a block breaks the current content flow while inline maintains it. Additionally, if a width property were applied to the a selector, it would not change the layout. When the content flow is disrupted by a block element, it remains broken, and the width always takes up the entire parent container width.

      inline and block are the most common browser default values. While the display property has many values, with a few exceptions, all remaining elements use one of these two values.

      Now that you have explored the differences between block and inline, return to styles.css in your text editor. In the a selector, remove the display: block and replace it with a color property with a value of hsl(215, 80%, 50%), which is a richer version of the blue used on the body. Then create an a:hover selector with a text-decoration property set to none. This will remove the underline when the link is hovered. The highlighted CSS in the following code block shows how this is written:

      styles.css

      ...
      a {
        color: hsl(215, 80%, 50%);
      }
      
      a:hover {
        text-decoration: none;
      }
      

      Save your changes to styles.css and refresh index.html in your web browser. The link will once again be inline with the text and will now be a lighter blue color, as shown in the following image:

      Large header text and smaller paragraph text in a dark blue-gray color on a light gray background with a blue underlined link.

      In this section, you set up the HTML and CSS files you will use throughout the tutorial. These files will be amended and modified regularly, so keep both files open in your text editor and remember to save regularly. You also learned about the default display values, inline and block, and changed the value of an inline element to block. In the next section, you will use the inline-block value, which combines the capabilities of inline and block.

      Using the inline-block Value

      Next, you will create a button element with a customizable width, rather than a button that takes up the whole width of the parent container. To do this, you will use the inline-block value, which maintains box model properties of the block value like margin and padding while also having the content flow properties of the inline value.

      The inline- prefix is available on several display values, including inline-flex, inline-grid, and inline-table. The inline-block value defines the box model of the element as a block, but it does not disrupt the content flow. Additionally, inline-block does not take up the full parent width, as block does. Instead, the inline-block element condenses down to only the width of its content. For shorter content, such as a button, this makes for a useful resizing of the element with block box model properties, such as margin.

      To begin working with inline-block, open index.html in your text editor. After the closing <p> tag, add an <a> tag with a class attribute set to button and an href attribute set to https://en.wikipedia.org/wiki/Terrestrial_planet. Inside that tag, add the text Learn more on Wikipedia. The highlighted HTML in the following code block demonstrates how this is written:

      index.html

      <div class="content-width">
        <h1>The Terrestrial Planets of the Solar System</h1>
      
        <p>
          ...
        </p>
      
        <a href="https://en.wikipedia.org/wiki/Terrestrial_planet" class="button">Learn more on Wikipedia</a>
      </div>
      

      Save your changes to index.html, then open styles.css in your text editor.

      In your styles.css file, add a class selector for .button. This will style the link you created in your index.html file. By default, an <a> has a display value of inline. For this step, change the display value to block for the button class, then add the additional highlighted styles from the following code block:

      styles.css

      ...
      a:hover {
        text-decoration: none;
      }
      
      .button {
        display:block;
        padding: 0.5rem 1.25rem;
        text-align: center;
        text-decoration: none;
        color: hsl(215, 20%, 95%);
        background: linear-gradient(to bottom, hsl(215, 80%, 60%), hsl(215, 80%, 40%));
      }
      

      The additional styles added to the .button element add padding, center the text, and remove the link underline. Additionally, the styles add a blue gradient of the same hue as the earlier versions of this blue with a near white text color.

      Save these changes to the styles.css, then return to your browser and refresh index.html. The button will fill the full width of the content area with a blue gradient. The following image shows how this will render in the browser:

      Large header text and smaller paragraph text in a dark blue-gray color on a light gray background with a blue button below the paragraph with white text. The button is as wide as the paragraph.

      Next, you will change the block value for the display property to inline-block. Return to styles.css in your text editor and change the display property value from block to inline-block, as highlighted in the following code block:

      styles.css

      ...
      .button {
        display: inline-block;
        padding: 0.5rem 1.25rem;
        text-align: center;
        text-decoration: none;
        color: hsl(215, 20%, 95%);
        background: linear-gradient(to bottom, hsl(215, 80%, 60%), hsl(215, 80%, 40%));
      }
      

      Save these changes to styles.css and then refresh index.html in your web browser. The width of the button has condensed from extending the full width of its parent to being just as wide as its content, plus the padding value. The following image demonstrates how the inline-block element renders in the browser:

      Large header text and smaller paragraph text in a dark blue-gray color on a light gray background with a blue button below the paragraph with white text. The button is only as wide as the text inside the button.

      Finally, return to styles.css to add in some last styling for the button. You will add styles to apply a 3D effect to the button by adding a border-radius, border, text-shadow, and box-shadow. Also, create a .button:hover selector and add a box-shadow and linear-gradien() that make a darker hover state. The highlighted CSS in the following code block show how to write these styles:

      styles.css

      ...
      .button {
        display: inline-block;
        padding: 0.5rem 1.25rem;
        text-align: center;
        text-decoration: none;
        color: hsl(215, 20%, 95%);
        background: linear-gradient(to bottom, hsl(215, 80%, 60%), hsl(215, 80%, 40%));
        border-radius: 0.25rem;
        border: 1px solid hsl(215, 80%, 35%);
        text-shadow: 0 -1px hsl(215, 80%, 35%);
        box-shadow: 0 1px hsl(215, 80%, 70%) inset;
      }
      
      .button:hover {
        box-shadow: 0 1px hsl(215, 80%, 60%) inset;
        background: linear-gradient(to bottom, hsl(215, 80%, 50%), hsl(215, 80%, 30%));
      }
      

      Save your changes to styles.css and then refresh the page in your web browser. Visually, the button now has more definition and depth, as shown in the following image:

      Blue gradient button with white text and a dark border.

      In this section, you used the inline-block value on a link to create a button that is large and clickable, but only as wide as the link’s text. You also learned how there are other inline- prefixed display values that allow for various display types that do not disrupt the content flow. In the next section, you will continue changing display values by switching table elements to block.

      Changing a Table to Use display: block

      Next, you will convert a whole table to use the display: block property value. A table requires HTML specific to the table element, and each child element of the table has its own default display value. For example, the <table> element has a display value of table, and the table cell, <td>, has a display value of table-cell. There can be many reasons why a table might need to change its display value, but most often it is for a small-screen device solution where the table doesn’t fit well.

      To begin working with a table’s display property, open index.html in your text editor. After the button link, add the highlighted HTML from the following code block:

      index.html

      ...
      <a href="https://en.wikipedia.org/wiki/Terrestrial_planet" class="button">Learn more on Wikipedia</a>
      
      <table>
        <caption>
          Terrestrial Planets Statistics
        </caption>
        <thead>
          <tr>
            <th>Name</th>
            <th>Radius</th>
            <th>Moons</th>
            <th>Gravity</th>
            <th>Wikipedia</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <th>Mercury</th>
            <td>2,439.7 km</td>
            <td>0</td>
            <td>3.7 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Mercury_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
          <tr>
            <th>Venus</th>
            <td>6,051.8 km</td>
            <td>0</td>
            <td>8.87 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Venus_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
          <tr>
            <th>Earth</th>
            <td>6,371.0 km</td>
            <td>1</td>
            <td>9.80665 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Earth_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
          <tr>
            <th>Mars</th>
            <td>3,389.5 km</td>
            <td>2</td>
            <td>3.72076 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Mars_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
        </tbody>
      </table>
      ...
      

      This table HTML creates a table called “Terrestrial Planets Statistics” by putting that name in the <caption> element, a necessary component of screen-reader accessible tables. Then the HTML creates a five-column table consisting of a header row and four data rows.

      Next, to add some visual styles to the table, open styles.css in your text editor. You will create a visual style that makes the caption like a header for the table. The table header row will become more distinct with a dark background, and you will create a zebra stripe effect with alternating background colors on the data rows. The highlighted CSS in the following code block demonstrates how these styles are written:

      styles.css

      ...
      table {
        border-collapse: collapse;
        width: 100%;
        margin: 3rem 0;
      }
      
      caption {
        font-size: 1.5rem;
        font-weight: 700;
        color: hsl(215, 25%, 25%);
        text-align: left;
        margin-bottom: 0.5em;
      }
      
      tr {
        text-align: center;
      }
      
      thead > tr {
        color: hsl(215, 25%, 100%);
        background-color: hsl(215, 80%, 20%);
      }
      
      tbody > tr:nth-child(even) {
        background-color: hsl(215, 50%, 93%);
      }
      
      tbody th {
        font-size: 1.125rem;
      }
      
      td, th {
        padding: 0.5rem;
      }
      

      Save your changes to styles.css and open index.html in your web browser. The table is styled with clear data and alignment, as shown in the following image:

      Table grid of data containing information about the four terrestrial planets.

      Open your local version of index.html on a smart phone, or scale your browser’s window down to about the size of a smart phone. The table will eventually start going off screen and will only be viewable by scrolling horizontally, as demonstrated in the following image:

      A phone containing a table going off screen, cutting off informations.

      This is a situation where changing the display value of the table elements can help provide a better viewing experience for those on smaller screens.

      Return to styles.css in your text editor and create a media query set to a max-width of 60rem. Normally, you would use min-width instead of max-width in your media queries to follow a mobile first design flow. However, since you will only change the style on small screens and then return to the browser default at a given screen size, in this example situation max-width requires the least work. Inside the media query, create a group combinator consisting of table, caption, thead, tbody, tr, th, and td. Then set the display property to block, as highlighted in the following code block:

      styles.css

      @media (max-width: 60rem) {
        table,
        caption,
        thead,
        tbody,
        tr,
        th,
        td {
          display: block;
        }
      }
      

      Save your changes to styles.css and return to index.html on your smartphone or in a small-size browser window. All the contents of the table are now stacked in one large column, with each row’s contents grouped together. The following image shows how this is rendered on a mobile phone:

      Contents of a table in a vertical stack.

      This change to the table’s display value creates two issues. The first is that the browser no longer recognizes the table as a table, and therefore will not be read to a screen reader as a table. The second is that some of the contents and styles are now not providing useful information. For starters, the table headers no longer provide visual connection to the data types. Secondly, the zebra stripes don’t provide as much information in this scenario.

      Return to styles.css in your text editor. First, remove thead from the group combinator. Next, create a new selector for the thead element and give it a display property set to a value of none. The display: none value completely removes an element visually from rendering in the browser. It is important to know that the none value also removes the element from the screen reader DOM, so the element is hidden from all users. The highlighted CSS in the following code block shows how this is set up:

      styles.css

      @media (max-width: 60rem) {
        table,
        caption,
        tbody,
        tr,
        th,
        td {
          display: block;
        }
      
        thead {
          display: none;
        }
      }
      

      Next, to begin addressing the style changes, start by adding a text-align property to the large group combinator with a value of left. Next, duplicate the selector used for the zebra stripes, tbody> tr:nth-child(even), and set the background-color to transparent. This will remove the zebra stripe effect on screens and windows smaller than 60rem, or 960px, wide. Then, make the Learn More button work as a full-width button on small screens. Create a table .button descendant selector with the display property set to block, which will cause the button to fill the width of the container. The highlighted CSS in the following code block illustrates how this looks:

      styles.css

      @media (max-width: 60rem) {
        table,
        caption,
        tbody,
        tr,
        th,
        td {
          display: block;
          text-align: left;
        }
      
        thead {
          display: none;
        }
      
        tbody > tr:nth-child(even) {
          background-color: transparent;
        }
      
        table .button {
          display: block;
        }
      }
      

      Save your changes to styles.css in your text editor and then refresh index.html in your browser. On small-screen devices, the content of the tables are now all left-aligned with the button spanning the width of the content. The following image shows how this is rendered in Safari on a mobile phone:

      A series of bold heading text with data information and a button for each group.

      In this section, you converted a table to a block element to make it more visually usable when the screen or browser window small. In the last section, you will improve the accessibility of the table both for sighted users and those using screen readers.

      Adding Small-Screen Context Elements

      Now that you have changed the display values for the table elements on a small screen, you can add some enhancements to make this view as useful as the large screen version. You will add some HTML that will help make the information more understandable on small screens. Then you will provide styling specifically for the small screen experience of the table information.

      To begin, open index.html in your text editor. To provide the table’s contextual information lost by hiding the thead element, you will add that header value to each cell inside a <span> element. For example, you will add <span>Radius: </span> before the value in the column containing the Radius information for the planet in each <td> element. Additionally, each <span> element will have a class attribute set to a value of label, so these elements can be quickly styled. The highlighted HTML in the following code block shows how to write the markup:

      index.html

      ...
        <tbody>
          <tr>
            <th>Mercury</th>
            <td><span class="label">Radius: </span>2,439.7 km</td>
            <td><span class="label">Moons: </span>0</td>
            <td><span class="label">Gravity: </span>3.7 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Mercury_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
          <tr>
            <th>Venus</th>
            <td><span class="label">Radius: </span>6,051.8 km</td>
            <td><span class="label">Moons: </span>0</td>
            <td><span class="label">Gravity: </span>8.87 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Venus_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
          <tr>
            <th>Earth</th>
            <td><span class="label">Radius: </span>6,371.0 km</td>
            <td><span class="label">Moons: </span>1</td>
            <td><span class="label">Gravity: </span>9.80665 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Earth_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
          <tr>
            <th>Mars</th>
            <td><span class="label">Radius: </span>3,389.5 km</td>
            <td><span class="label">Moons: </span>2</td>
            <td><span class="label">Gravity: </span>3.72076 m/s<sup>2</sup></td>
            <td>
              <a href="https://en.wikipedia.org/wiki/Mars_(planet)" class="button">
                Learn More
              </a>
            </td>
          </tr>
        </tbody>
      ...
      

      Save your changes to index.html and return to your browser to examine the small-screen view. The contextual information around what each data point means is now visually recognizable. The following image shows how this will render in the browser:

      A series of bold heading text with contextual data information and a button for each group.

      Next, return to styles.css in your text editor. These labels will be present on larger screens when they are no longer necessary, so they will need some styling to fix this issue. Due to the max-width media query approach, this means that the default styles for .label outside the query need to be set to display: none in order to hide the content on large screens. Then inside the media query, create a .label selector with a display property set to inline, since it should be in the content flow containing the value. To create a visual separation between the label and data point, add a font-weight property set to 700. The highlighted CSS in the following code block demonstrates how and where to apply these additions:

      styles.css

      ...
      td, th {
        padding: 0.5rem;
      }
      
      .label {
        display: none;
      }
      
      @media (max-width: 60rem) {
        ...
        .label {
          display: inline;
          font-weight: 700;
        }
      }
      

      Save your changes to styles.css and once again return to your browser and refresh index.html. The browser will render the labels as inline content that is bold, as shown in the following image:

      A series of bold heading text with bold contextual labels and data information and a button for each group.

      While still in your web browser on a large screen, expand the window out until the table returns to the tabular style. The labels are now hidden providing distinctive visual and accessible information for each scenario. The following image shows how the large screen version of the table is now rendered:

      Table grid of data containing information about the four terrestrial planets.

      Finally, you will provide additional styling for each table row that will make them appear as their own little tables.

      Open styles.css in your text editor. Inside the media query, add a tbody th descendant selector and add the color properties and values from the thead > tr selector. This will give the same dark blue background and near-white text color for each planet name. Then, add a border-radius property set to 0.5rem 0.5rem 0 0 to create a rounded top to the heading. The highlighted CSS of the following code block shows how to style the planet name:

      stlyes.css

      ...
      @media (max-width: 60rem) {
        ...
        .label {
          display: inline;
          font-weight: 700;
        }
      
        tbody th {
          color: hsl(215, 25%, 100%);
          background-color: hsl(215, 80%, 20%);
          border-radius: 0.5rem 0.5rem 0 0;
        }
      }
      

      Next, you will add some definition to the datasets and give some spacing between each grouping. First, create a tbody > tr selector inside the media query with a border property set to 1px solid hsl(215, 80%, 20%). Then add a border-radius property with a value of 0.5rem, which will round the corner of all sides of the container. Lastly, create a tbody > tr + tr adjacent sibling combinator, with a margin-top property set to 1rem, which will give space between each group of data. The highlighted CSS in the following code block demonstrates how this is written:

      stlyes.css

      ...
      @media (max-width: 60rem) {
        ...
        tbody th {
          color: hsl(215, 25%, 100%);
          background-color: hsl(215, 80%, 20%);
          border-radius: 0.5rem 0.5rem 0 0;
        }
      
        tbody > tr {
          border: 1px solid hsl(215, 80%, 20%);
          border-radius: 0.5rem;
        }
      
        tbody > tr + tr {
          margin-top: 1rem;
        }
      }
      

      Finally, you will add in a zebra stripe effect specifically for each td element. This is done by creating a td:nth-child(even) pseudo-class selector. Then use the same background-color property and value from before, as highlighted in the following code block:

      stlyes.css

      ...
      @media (max-width: 60rem) {
        ...
        tbody > tr + tr {
          margin-top: 1rem;
        }
      
        td:nth-child(even) {
          background-color: hsl(215, 50%, 93%);
        }
      }
      

      Save your changes to styles.css and open index.html on a small-width browser or smartphone. Each row from the table will now appear as though it were a table with a header, data points, and a button to learn more. The following image shows how this is rendered in on a smartphone browser:

      Groups of data blocks, with the header in white on a dark background, and data points in alternating rows of light blue and white background.

      In this last section, you used the display property to show and hide pertinent information that was contextual to the viewing scenario of a small-screen device. You also provided styling to the small-screen table to make it more accessible and usable.

      Conclusion

      There are many possibilities when working with the display property. In this tutorial, you learned about the default values of block and inline. You changed an <a> element to inline-block, which gave it a special combination of both block and inline. You then changed all the elements of a <table> to be block on a small screen and set them to return to their default table display values on a large screen. Lastly, you used the none value to hide content when and where necessary to users of all abilities. The display property is a powerful feature and has even more values available to further manipulate how the box model functions and affects elements.

      If you would like to read more CSS tutorials, try out the other tutorials in the How To Style HTML with CSS series.



      Source link

      How To Use Relationships to Select HTML Elements with CSS


      The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Selectors are what web browsers use to find and apply specific styles to an element via CSS. You can apply these styles broadly with type selectors that select many elements of the same kind. In addition to targeting specific attributes of an element like id or class, it is possible to select an element based on its relationship or proximity to another element. For example, you can select an HTML element that follows a preceding element or the first element in a series.

      In this tutorial, you will use several CSS-relationship-based approaches to select and style elements on an HTML page. You will create a page of content with different styling scenarios for each relationship selector. You will use the descendant combinator, child combinator, general sibling combinator, and adjacent sibling combinator, as well as the first-, last-, only-, and nth-child pseudo-class selectors. These selectors apply styles based on the relative conditions of surrounding elements, as opposed to the direct method of traditional selectors.

      Prerequisites

      Setting Up the Initial HTML and CSS

      To start, you will set up the HTML and CSS code that you will work on throughout the rest of the tutorial.

      Begin by opening index.html in your text editor. Then, add the following HTML to the file:

      index.html

      <!doctype html>
      <html>
        <head>
        </head>
        <body>
        </body>
      </html>
      

      Next, go to the <head> tag and add a <meta> tag to define the character set for the HTML file. Then set the title of the page, add a <meta> tag defining how mobile devices should render the page, and finally load the CSS file that you will make later with a <link> tag. These additions are highlighted in the following code block. You will encounter this highlighting method throughout the tutorial as code is added and changed:

      index.html

      <!doctype html>
      <html>
        <head>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <title>Relationship Selectors</title>
          <link rel="stylesheet" href="https://www.digitalocean.com/community/tutorials/styles.css">
        </head>
        <body>
        </body>
      </html>
      

      After adding the <head> content, move to the <body> element, where you will add content for a page talking about CSS selectors. Add the highlighted section from this code block to your index.html file in your text editor:

      index.html

      <!doctype html>
      <html>
        <head>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <title>Relationship Selectors</title>
          <link rel="stylesheet" href="https://www.digitalocean.com/community/tutorials/styles.css" />
        </head>
        <body>
          <h1>Relationship Selectors</h1>
          <main class="content-width">
          </main>
        </body>
      </html>
      

      Be sure to save these additions to index.html. The <h1> element displays the title of the page. The <main> element with a class attribute of content-width will contain the contents of the page, which you will add throughout the tutorial.

      Next, create a new file called styles.css in the same directory as your index.html file, then open the new file in your text editor. This file will load the styles that the browser will then apply to the content of index.html. Add the following CSS code to your styles.css file:

      styles.css

      body {
        font-family: system-ui, sans-serif;
        color: #333;
      }
      
      .content-width {
        width: 90%;
        margin: 2rem auto;
        max-width: 70ch; 
      }
      
      section{
        margin: 4rem 0;
      }
      
      h1 {
        text-align: center;
      }
      
      h2 {
        color: mediumblue;
      }
      

      In this code, the body type selector defines new defaults for the font-family and color values on the page. The .content-width class selector is set up to be 90% of the page’s width and to grow to a maximum width of 70 character widths of the current font-size. 70 characters is the ideal maximum length of a line of text. The margin on the .content-width property keeps space above and below the element and keeps the container horizontally centered. There will be several <section> elements on this page, so the section type selector applies a margin to give ample space between each grouping. Lastly, the h1 and h2 type selectors set the <h1> content to be centered and the <h2> content to have a color of mediumblue.

      In this section you, set up the starting points for your HTML and CSS files. In the next section, you will add some more content to index.html, then use the descendant combinator to apply styles with CSS.

      Descendant Combinators

      When working with relationship-based selectors, you will come across familial terminology, such as parent, child, ancestor, and in this case, descendant. The descendant combinator is a space-separated list of selectors that matches the HTML structure in order to apply styles to elements that have a particular ancestor. The last selector in the list is the one that receives the styles, and is the descendant of the previous selectors in the list.

      The descendant combinator is the quickest way to scope a style. Scoping is the method of providing additional details to increase the specificity of a selector. The descendant combinator aids scoping by prepending the selector with an ancestor selector. For example, the a type selector will get all the <a> tags on a page, but the header a descendant selector will select only the <a> tags inside of a <header> element.

      To begin using the descendant combinator, open index.html in your text editor. Create a <section> element with a class attribute of descendant. Inside the <section> element, add an <h2> element containing Descendant Combinator Selector, then add two <p> elements and fill them with content from Cupcake Ipsum. Wrap the second <p> element in a <blockquote>. The highlighted HTML in the following code block demonstrates how this will be set up:

      index.html

      ...
      <main class="content-width">
        <section class="descendant">
          <h2>Descendant Combinator Selector</h2>
          <p>Sweet roll pudding ice cream jelly beans caramels cookie caramels. Macaroon cheesecake cookie marzipan icing jujubes. Chocolate bar jelly-o wafer toffee cookie muffin soufflé lemon drops bonbon. Soufflé danish gingerbread sweet roll marzipan carrot cake.</p>
      
          <blockquote>
            <p>Bear claw pastry tootsie roll biscuit jujubes oat cake toffee wafer lemon drops. Croissant pie lemon drops cake chupa chups chocolate bar chupa chups marshmallow. Cake pudding icing tiramisu tiramisu pastry topping. Gingerbread shortbread lollipop chocolate bar icing.</p>
          </blockquote>
        </section>
      </main>
      ...
      

      Save your changes to index.html then open styles.css in your text editor. Add a .descendant class selector followed by a space, then a blockquote type selector. This will create a selector that only applies styles to a blockquote element that is inside an element with a class attribute containing descendant. The highlighted CSS in the following code block demonstrates this selector with styles for the blockquote element:

      styles.css

      ...
      h2 {
        color: mediumblue;
      }
      
      .descendant blockquote {
        margin: 2rem 0;
        padding: 1rem 1rem 1rem 2rem;
        border-left: 0.125rem indigo solid;
        background-color: lavender;
      }
      

      Save your changes to styles.css and open index.html in your browser. The properties used on this blockquote element provide additional spacing above and below with the margin property. Then, the padding property gives the content space inside the container. Lastly, the container is visually defined by a combination of the border-left property creating a solid indigo line and a lavender backdrop applied with the background-color property. The following screenshot shows how this code will render in the browser:

      Large bold blue headline followed by a smaller paragraph of black text. Below the paragraph is a light purple box with a darker purple border on the left side. Inside the box is another paragraph of black text.

      You can also apply descendant combinator selectors to a descendant element regardless of how deep in the HTML that element is relative to the ancestor selector. Similar to how the previous code set styles to the <blockquote> element inside of the .descendant class selector, you will next apply styles to all <p> elements, regardless of the element they are contained in.

      Return to your styles.css file in your text editor. Then, add a new descendant combinator selector for a p element selector with an ancestor of .descendant. Inside the selector block, set the line-height property to a value of 1.5. The highlighted CSS in the following code block shows how this will look:

      styles.css

      ...
      .descendant blockquote {
        margin: 2rem 0;
        padding: 1rem 1rem 1rem 2rem;
        border-left: 0.125rem indigo solid;
        background-color: lavender;
      }
      
      .descendant p {
        line-height: 1.5;
      }
      

      Save your changes to styles.css and open index.html in your browser. The lines of text for both <p> elements are now larger, despite one of those <p> elements being inside the <blockquote> element. The following image illustrates how this will render in the browser:

      Large bold blue headline followed by a paragraph of black text with a more legible line height. Below the paragraph is a light purple box with a darker purple border on the left side. Inside the box is another paragraph of black text with similar line height as the previous paragraph.

      Finally, return to your styles.css file in your text editor. You will create a new descendant selector to apply styles directly to the <p> element inside the <blockquote> element. Start by writing out .descendant blockquote p, which will tell the browser to find the <p> elements on the page that is somewhere inside a <blockquote> element, which in turn is inside an element with a class attribute of descendant. Then in the selector block, add a font-size property set to 1.25rem and a color property with #222 as the value. The highlighted CSS in the following code block demonstrates the necessary structure:

      styles.css

      ...
      .descendant p {
        line-height: 1.5;
      }
      
      .descendant blockquote p {
        font-size: 1.25rem;
        color: #222;
      }
      

      Save your changes to styles.css and open index.html in your browser. The font-size of the <p> element’s content inside the <blockquote> will now be much larger and have a slightly softer gray color, as shown in the following image:

      Large bold blue headline followed by a smaller paragraph of black text. Below the paragraph is a light purple box with a darker purple border on the left side. Inside the box is another paragraph of larger black text.

      In this section, you used the descendant combinator selector to scope styles to elements that are found inside of another element to apply styles. In the next section, you will use the child combinator selector to select only the first-level children of an element.

      Child Combinator Selectors

      When scoping styles, there are times that you don’t want all elements within an ancestor selector, just those immediately inside the element. For example, you might want to style all the top-level links in a navigation bar, and not any links that are contained in any sub navigation elements. For these moments when only the children of a given parent need to be styled, you can use the child combinator selector.

      Before working with this new selector, return to index.html in your text editor and add the highlighted HTML from the following code block inside the <main> element and after the previous <section> element:

      index.html

      ...
      <main class="content-width">
        ...
        <section class="child">
          <h2>Child Combinator Selector</h2>
      
          <p>Sweet roll carrot cake cake chocolate bar sugar plum. Cheesecake caramels jelly-o sugar plum icing muffin marzipan chocolate bar jujubes. Dessert cotton candy gummies chocolate cake sweet.</p>
      
          <div>
            <p>Liquorice sesame snaps chocolate bar soufflé oat cake candy canes fruitcake lollipop candy. Macaroon wafer cotton candy tootsie roll jelly halvah. Icing powder soufflé toffee dessert gummies bear claw donut cake.</p>
          </div>
        </section>
      </main>
      ...
      

      Save your changes to index.html then open styles.css in your text editor.

      First, you will extend the .descendant p selector with a line-height property to include the <p> elements found inside the <section> with the child class. You will accomplish by using a general combinator, which allows multiple selectors to share the same styles. A comma is needed between each selector to apply the styles. Add a comma after the .descendant p selector, then add a .child p descendant combinator, as demonstrated in the following highlighted code:

      styles.css

      ...
      .descendant p,
      .child p {
        line-height: 1.5;
      }
      ...
      

      Save your changes to styles.css and open index.html in your browser. The content in the new section will now have a larger space between each line of text. The following image depicts how this will appear in the browser:

      Large bold blue headline followed by two smaller sized black text paragraphs.

      Next, to select only the <p> element, which is the direct child of the <section class="child"> element, you will use the child combinator selector. This is constructed by writing the parent selector followed by the greater-than sign (>) and then the child selector.

      Return to styles.css in your text editor and go to the end of the file. Create a child combinator selector by setting the parent selector as .child and the child selector as p. Then inside the selector block set the color property to a named value of forestgreen. The highlighted CSS in the following code block shows how this is written:

      styles.css

      ...
      .descendant blockquote p {
        font-size: 1.25rem;
        color: #222;
      }
      
      .child > p {
        color: forestgreen;
      }
      

      Save your changes to styles.css and open index.html in your browser. Only the first <p> element has text set to the forestgreen color. The <div> element wrapping the second <p> element changes the relationship to the <section> element from a child to a grandchild. Because of this, that <p> element is invalid for the child combinator selector. The following image illustrates how this is rendered in the browser:

      Large bold blue headline followed by a smaller sized green text paragraph then a similar sized black text paragraph.

      In this section, you used the child combinator selector to select and apply styles to the immediate children of a parent element. In the next section, you will work with relationships of sibling elements to apply styles to elements when they have a common parent.

      Sibling Combinator Selectors

      The general sibling combinator provides a way to scope styling to elements that come after a specific element and have the same parent element, but which may not be next to each other. Often this will occur when the HTML is generally known but not predictable, such as dynamically generated content.

      First, you will need HTML siblings to use the selector. Return to index.html in your text editor. Then, add the highlighted HTML from the following code block before the closing </main> tag:

      index.html

      ...
      <main class="content-width">
        ...
        <section class="general-sibling">
          <h2>General Sibling Combinator Selector</h2>
      
          <p>Donut dessert jelly-o pie gingerbread jelly-o gummies biscuit gummies. Fruitcake jelly bonbon croissant carrot cake gummies. Candy canes apple pie liquorice gummi bears shortbread lemon drops jelly-o marzipan halvah. Jujubes chocolate bar tart bear claw sweet.</p>
      
          <div>
            <p>Carrot cake soufflé oat cake gummies marzipan sugar plum pastry jujubes. Tootsie roll pastry danish cake cake cake jelly sesame snaps. Donut pastry brownie brownie pie croissant</p>
          </div>
      
          <p>Gummies apple pie gingerbread cheesecake chupa chups cookie jelly beans. Tootsie roll dessert liquorice jujubes apple pie biscuit gummies biscuit jelly-o. Cake candy canes danish sugar plum biscuit lemon drops icing.</p>
      
          <p>Jelly beans candy candy cookie cotton candy. Liquorice gummies biscuit dragée sesame snaps oat cake tiramisu. Powder sweet dessert chupa chups ice cream sweet.</p>
        </section>
      </main>
      ...
      

      Save your changes to index.html, then open styles.css in your text editor.

      Next, you will extend the grouping selector with a line-height property to include the <p> elements found inside the <section> with the general-sibling class. Again, this is accomplished by adding a comma after the .child p selector and adding a .general-sibling p descendant combinator, as shown in the following highlighted CSS:

      styles.css

      ...
      .descendant p,
      .child p,
      .general-sibling p {
        line-height: 1.5;
      }
      ...
      

      Save your changes to styles.css and refresh index.html in your browser. The content in the new section will now have a larger space between each line of text. The following image depicts how this will appear in the browser:

      Large bold blue headline followed by four smaller-sized black text paragraphs.

      Next, you will write the styles for the sibling <p> elements that come after another <p> element of the same parent. This is done by writing a selector, followed by a tilde (~), followed by the selector of the sibling you wish to style.

      Return to styles.css in your text editor and add a new selector for .general-sibling p. This will find the <p> elements with a parent that has a class attribute with general-sibling. Then add the tilde symbol followed by a p element selector. Inside the selector block, set the color property to the named value of lightseagreen, as shown in the highlighted CSS of the following code block:

      styles.css

      ...
      .child > p {
        color: forestgreen;
      }
      
      .general-sibling p ~ p {
        color: lightseagreen;
      }
      

      Save your changes to styles.css and return to your browser to refresh index.html. The following image showcases how this code will render in the browser:

      Large bold blue headline followed by two smaller-sized black text paragraphs then two similar-sized teal text paragraphs.

      Only the last two of the four paragraphs will have the lightseagreen color. This is because the first paragraph is the initializing selector, the .general-sibling p part of the combinator, meaning the subsequent <p> elements will receive the styling. The second paragraph of text is inside a <p> element, but because it is nested inside a <div> element it is no longer a sibling of the initializing selector.

      Sibling selectors do not have to be of the same element type. To demonstrate this, return to the styles.css file in your text editor and change the first p in the selector to a div instead, as highlighted in the following code block:

      styles.css

      ...
      .general-sibling div ~ p {
        color: lightseagreen;
      }
      

      Save that small change to styles.css and refresh index.html in your browser. Visually nothing changed, but the way the styles are applied by the browser did change. The elements receiving the styles must be <p> elements that are sibling subsequents to the selector before the tilde. Since the order of the HTML is <p />, <div />, <p />, then <p />, the results of both general sibling selectors are the same. The first <p> element does not receive the styles because, though it is a sibling, it comes before the initializing .general-sibling div selector.

      In this section, you used the general sibling combinator to apply styles to any sibling elements of a certain kind. In the next section, you will use the adjacent sibling combinator to apply styles to the sibling immediately after an element.

      Adjacent Sibling Combinator Selectors

      If you only need to apply a style when two particular elements are next to each other in the HTML, the adjacent sibling combinator will help select the appropriate element. This can be useful when applying additional space between a heading text and a body text, or to add a divider between elements.

      To start working with the adjacent sibling combinator, first open index.html in your text editor. Then, inside the <main> element, add the highlighted HTML from the following code block:

      index.html

      ...
      <main class="content-width">
        ...
        <section class="adjacent-sibling">
          <h2>Adjacent Sibling Combinator Selector</h2>
      
          <p>Donut dessert jelly-o pie gingerbread jelly-o gummies biscuit gummies. Fruitcake jelly bonbon croissant carrot cake gummies. Candy canes apple pie liquorice gummi bears shortbread lemon drops jelly-o marzipan halvah. Jujubes chocolate bar tart bear claw sweet.</p>
      
          <div>
            <p>Carrot cake soufflé oat cake gummies marzipan sugar plum pastry jujubes. Tootsie roll pastry danish cake cake cake jelly sesame snaps. Donut pastry brownie brownie pie croissant</p>
          </div>
      
          <p>Gummies apple pie gingerbread cheesecake chupa chups cookie jelly beans. Tootsie roll dessert liquorice jujubes apple pie biscuit gummies biscuit jelly-o. Cake candy canes danish sugar plum biscuit lemon drops icing.</p>
      
          <p>Jelly beans candy candy cookie cotton candy. Liquorice gummies biscuit dragée sesame snaps oat cake tiramisu. Powder sweet dessert chupa chups ice cream sweet.</p>
        </section>
      </main>
      

      Save your changes to index.html, then open styles.css in your text editor. Extend the selector grouping of the line-height with .adjacent-sibling p, as highlighted in the following code block:

      styles.css

      ...
      .descendant p,
      .child p,
      .general-sibling p,
      .adjacent-sibling p {
        line-height: 1.5;
      }
      ...
      

      Next, go to the last line of the styles.css file. Here, you will write an adjacent sibling combinator selector to apply a top border and extra padding to a <p> element that is preceded by another <p> element. The highlighted CSS in the following code block displays how this is written:

      styles.css

      ...
      .general-sibling div ~ p {
        color: lightseagreen;
      }
      
      .adjacent-sibling p + p {
        border-top: 1px solid black;
        padding-top: 1em;
      }
      

      Since this style should only be applied to a <p> element inside the <section class="adjacent-sibling"> element, the first selector must use a descendant combinator. The second element in the selector only needs to use an element selector, since that is the adjacent element to the sibling.

      Note: It is important to remember when working with the sibling selectors that the last selector in the sequence is the element that is selected. Let’s say an adjacent sibling combinator was written as .adjacent-sibling p + .adjacent-sibling p. The intent of this code may be to select the <p> after a <p> inside an ancestor of .adjacent-sibling. But instead, this adjacent sibling selector will try to target the <p> inside an ancestor of .adjacent-sibling that comes immediately after a <p> sibling, which in turn is a descendant of another element with a class of adjacent-sibling.

      Save your changes to styles.css and refresh index.html in your browser. The border will be rendered above the last paragraph, since this is where a <p> is next to a <p>. The extra padding on top visually compensates for the margin so there is equal spacing above and below the line, as shown in the following image:

      Large bold blue headline followed by four smaller-sized black text paragraphs with a thin black rule line between the third and fourth paragraphs.

      This selector is not limited to like siblings; it can be a sibling selector of any kind. Return to styles.css and create a new adjacent sibling selector to add a red border between the <div> element and the adjacent <p> element, along with some extra top padding. The highlighted CSS in the following code block demonstrates how this will be set up:

      styles.css

      ...
      .adjacent-sibling p + p {
        border-top: 1px solid black;
        padding-top: 1em;
      }
      
      .adjacent-sibling div + p {
        border-top: 1px solid red;
        padding-top: 1em;
      }
      

      Save your changes to styles.css and open index.html in your browser. There is now a red line between the second and third paragraphs, since this is where a <div> element is next to a <p> element. The following image shows how this will be rendered in the browser:

      Large bold blue headline followed by four smaller-sized black text paragraphs with a thin red rule line after the second paragraph and a thin black rule line between the third and fourth paragraphs.

      In this section, you used the adjacent sibling combinator to apply styles to the element immediately following a sibling element. In the next section, you will use the first child pseudo-class to apply styles to the first element of a parent.

      first-child Pseudo-Class Selector

      When it comes to working with specific child elements, CSS provides pseudo-class selectors to refine the selection process. A pseudo-class selector is a state related to the condition of the selector. In this section, you will target elements that are the first child, meaning the first nested element, of a specified or unspecified parent element.

      To begin, open index.html in your text editor. Then, inside the <main> element, add the highlighted HTML from the following code block:

      index.html

      ...
      <main class="content-width">
        ...
        <section>
          <h2>First and Last Child Pseudo-Class Selector</h2>
          <ul>
            <li>Sugar plum gingerbread</li>
            <li>Sesame snaps sweet ice cream</li>
            <li>Jelly beans macaroon dessert</li>
            <li>Chocolate cheesecake</li>
            <li>Sweet roll pastry carrot cake</li>
            <li>Sugar plum tart cake</li>
            <li>Pudding soufflé</li>
            <li>Marshmallow oat cake</li>
          </ul>
        </section>
      </main>
      

      This HTML creates an unordered list, as defined by the <ul> element, with eight list items (<li>) nested inside. This will create a bulleted list of content by default in the browser.

      Save these changes to index.html then open styles.css in your text editor.

      In your CSS file, add a ul element selector. This section will not require any class-related scoping. Then inside the selector block add the property list-style with a value of none, which will remove the bulleted list styling. Set the margin property to 1rem 0 and the padding property to 0, which will override the browser default styles. The highlighted CSS in the following code block demonstrates how to set this up:

      styles.css

      ...
      .adjacent-sibling div + p {
        border-top: 1px solid red;
        padding-top: 1em;
      }
      
      ul {
        list-style: none;
        margin: 1rem 0;
        padding: 0;
      }
      

      Save your changes to styles.css and open index.html in your browser. The unordered list will no longer have bullets and will be aligned with the heading text, as shown in the following image:

      Large bold blue headline followed by an unordered list of eight items.

      Next, to provide some default styling to the list items, create a li element selector. Apply a padding property in the selector block with a value of 0.5rem 0.75rem. Then, add a light green background-color property with hsl(120, 50%, 95%) as the value. Lastly, add a border property set to 1px and solid with a slightly darker green color using hsl(120, 50%, 80%), as highlighted in the following code block:

      styles.css

      ...
      ul {
        list-style: none;
        margin: 1rem 0;
        padding: 0;
      }
      
      ul li {
        padding: 0.5rem 0.75rem;
        background-color: hsl(120, 50%, 95%);
        border: 1px solid hsl(120, 50%, 80%);
      }
      

      Save these changes to styles.css and open index.html in your browser. Each list item now has a light green background color with a darker green border, with text inset by the padding property. The following image shows how this will render in the browser:

      Large bold blue headline followed by an unordered list of eight items each in a light green box with a green border.

      The top and bottom borders of the list items double up the thickness of the border between items, making the border thickness inconsistent. To address this situation, return to styles.css in your text editor. Then, add a new adjacent sibling combinator to select an <li> element that comes after an <li> element inside a <ul> element, as depicted in the following code block:

      styles.css

      ...
      ul li {
        padding: 0.5rem 0.75rem;
        background-color: hsl(120, 50%, 95%);
        border: 1px solid hsl(120, 50%, 80%);
      }
      
      ul li + li {
        border-top: none;
      }
      

      Save that addition to styles.css and refresh index.html in your browser. The extra thick line between list items has been addressed by removing the border from the top of any list item that comes after another list item. The following image showcases how this will appear in the browser:

      Large bold blue headline followed by an unordered list of eight items each in a light green box with a green border.

      Now, return to styles.css to apply rounded corners to the top of the first list item. Since this needs to apply to only the first list item of an unordered list, you can use the child combinator selector. This will ensure that only the first direct child of the unordered list is selected. After the li element selector, append :first-child immediately without a space. For the rounded corner style on the top use the border-radius property with the value set to 0.75rem 0.75rem 0 0, which will add the rounded corners to the top left and top right corners. The highlighted CSS in the following code block shows how this is written:

      styles.css

      ...
      ul li + li {
        border-top: none;
      }
      
      ul > li:first-child {
        border-radius: 0.75rem 0.75rem 0 0;
      }
      

      Save this change to styles.css and return to the browser to refresh index.html. The first item in the unordered list now has rounded corners on the top side of the element. The following image illustrates how this is rendered in the browser:

      Large bold blue headline followed by an unordered list of eight items each in a light green box with a green border. The first item in the list has rounded corners.

      In this section, you created styles for a list and applied rounded corners to the first child <li> element of the <ul> parent element. In the next section, you will style the <li> at the end of the list with the last-child pseudo-class selector.

      last-child Pseudo-Class Selector

      In the same way that the first-child pseudo-class selector captures the first element of a parent, the last-child pseudo-class selector captures the last element of a parent element. In the previous section, you added rounded corners to the top of the first list item. In this section, you will add rounded corners to the bottom of the last item.

      To begin, return to styles.css in your text editor. After the selector block for the :first-child, add a similarly formatted child combinator with a :last-child on the li element selector. In the selector block, add a border-radius property and then for the value use 0 0 0.75rem 0.75rem. This value will set the top values to 0 and the bottom right and bottom left curve values to 0.75rem. The highlighted CSS in the following code block show how this is composed:

      styles.css

      ...
      ul > li:first-child {
        border-radius: 0.75rem 0.75rem 0 0;
      }
      
      ul > li:last-child {
        border-radius: 0 0 0.75rem 0.75rem;
      }
      

      Save your changes to styles.css and open index.html in your browser. The whole unordered list now looks like a box with equal rounded corners. The following images demonstrates how this is rendered in the browser:

      Large bold blue headline followed by an unordered list of eight, items each in a light green box with a green border. The first and last items in the list have rounded corners.

      In this section, you used the last-child pseudo-class to apply styles to the last <li> element in an unordered list. In the next, section you will write styles for when there is only one child element.

      only-child Pseudo-Class Selector

      When applying styles to contents that can change or update, there may be instances when there is only one child element. In those instances, the element is both the first and the last child, which can cause the pseudo-classes to overwrite each other’s styles. For this scenario there is another pseudo-class selector specifically for the only child scenario.

      To start, open index.html in your text editor and add the highlighted HTML from the following code block inside the <main> element and after the previous <section> element:

      index.html

      ...
      <main class="content-width">
        ...
        <section>
          <h2>Only Child Pseudo-Class Selector</h2>  
          <ul>
            <li>Sweet roll pastry carrot cake</li>
          </ul>
        </section>
      </main>
      

      Save the changes to index.thml then return to your browser and refresh the page. The browser is applying the :first-child rounded corners on the top, but then the :last-child rounded corner property overwrites the first. This results in the single list item having sharp corners on top and rounded corners on the bottom. The following image shows the browser rendering of the code:

      Large bold blue headline followed by an unordered list of one item with a light green background, green border, rounded corners on the bottom of the shape.

      Return to your text editor and open styles.css. To address this scenario, you will use the :only-child pseudo-class selector on the li portion of a child combinator. Then, for the border-radius property, set the value to a single 0.75rem, which will apply the curve to all four corners. The highlighted CSS in the following code block shows how this is written:

      styles.css

      ...
      ul > li:last-child {
        border-radius: 0 0  0.75rem 0.75rem;
      }
      
      ul > li:only-child {
        border-radius: 0.75rem;
      }
      

      Save these additions to styles.css, return to your browser, and refresh index.html. The single list item now has rounded corners on all sides, as shown in the following image:

      Large bold purple headline followed by an unordered list of one item with a light green background, green border, rounded corners on all four corners of the shape.

      In this section, you used the only-child pseudo-class selector to apply styles to a single <li> element in an unordered list. In the next section, you will use a pseudo-class selector to apply styles to any specific child element based on its numerical count within the parent.

      nth-child Pseudo-Class Selector

      The nth-child pseudo-class selector allows you to set patterns for the selection of child elements. Other selectors use characteristics of an element, such as an attribute value, to find matching HTML elements. The nth-child pseudo-class selector targets HTML elements by a given numerical position within their parent. The term nth is a mathematical phrase referring to an unidentified number in a series. This particular selector enables the selection of even and odd numbered children and specific numbered elements in the sequence.

      To set up the HTML for this selector, open index.html in your text editor. Then, add the highlighted portion from the following code block after the last </section> tag:

      index.html

      ...
      <main class="content-width">
        ...
        <section>
          <h2>Nth Child Pseudo-Class Selector</h2>
          <ol>
            <li>Caramel marshmallows</li>
            <li>Gummi bears</li>
            <li>pudding donut</li>
            <li>Chocolate bar</li>
            <li>Lemon drops</li>
            <li>Lollipop</li>
            <li>Danish soufflé</li>
          </ol>
        </section>
      </main>
      

      This code sets up an ordered list, as defined by the <ol> element. Unlike the <ul>, which marks each list item with a bullet point, the <ol> marks each item with a number in sequence.

      Be sure to save those changes to index.html. Then return to styles.css in your text editor. You will set up some adjusted stlyes for the ordered list and the list items. Create an ol element selector with a padding property set to 0. Next, add a list-style-position property with a value of inside; this will move the generated number to be inside the <li> element’s box model. Lastly, create an ol li descendant combinator with a padding property set to 0.25rem. Reference the highlighted CSS of the following code block for how this is to be written:

      styles.css

      ...
      ul > li:only-child {
        border-radius: 0.75rem;
      }
      
      ol {
        padding: 0;
        list-style-position: inside;
      }
      
      ol li {
        padding: 0.25rem;
      }
      

      Save your changes to styles.css, then open a web browser and load your index.html file. The new section will be rendered with a list of seven items, each beginning with their numerical value in the sequence, as illustrated in the following image:

      Large bold blue headline followed by an ordered list of seven items in black text.

      To begin working with the nth-child pseudo-class, return to styles.css in your text editor. The selector is set up like the previous pseudo-classes, but with a parenthesis at the end. This parenthesis contains the word value or numeric value to select the elements. To select all the even numbered list items, create a descendant combinator for ol and li. Then, add :nth-child() and inside the parenthesis add the word even. In the selector block, set the background-color property to aliceblue, as highlighted in the following code block:

      styles.css

      ...
      ol li {
        padding: 0.25rem;
      }
      
      ol li:nth-child(even) {
        background-color: aliceblue;
      }
      

      Save your changes to styles.css and open index.html in your browser. The second, fourth, and sixth items in the list now have a light blue background. This is how to create a style known as zebra stripes, which helps legibility with long lists of information. The following image demonstrates how this is rendered in the browser:

      Large bold blue headline followed by an ordered list of seven items in black text, alternating background betwen white and light blue.

      Next, return to styles.css in the text editor and do the same thing for the odd-numbered list items. Create another descendant combinator with the :nth-child() pseudo-class selector. This time, inside the parenthesis add the word value odd. Then in the selector block set the background-color property to lavenderblush, a light pink color. The following highlighted code shows how to set this up:

      styles.css

      ...
      ol li:nth-child(even) {
        background-color: aliceblue;
      }
      
      ol li:nth-child(odd) {
        background-color: lavenderblush;
      }
      

      Save that change to styles.css and reload index.html in the browser. The list now alternates between lavenderblush and aliceblue, with the new color on the first, third, fifth, and seventh list items. The following image shows how this will appear:

      Large bold blue headline followed by an ordered list of seven items in black text, alternating background betwen pink and light blue.

      Lastly, a numeric value can be inserted instead of a word value. Return to styles.css and add another ol li:nth-child() selector, this time with a 4 inside the parentheses. This will select the fourth item in the list. To make that item stand out, add a color property set to white and a background-color property set to indigo, as highlighted in the following code block:

      styles.css

      ...
      ol li:nth-child(odd) {
        background-color: lavenderblush;
      }
      
      ol li:nth-child(4) {
        color: white;
        background-color: indigo;
      }
      

      Save your changes to styles.css and open index.html in your browser. The odd and even items retain their alternating zebra stripe styling, but the fourth item now has a purple-colored background with white text. The following image shows how this is rendered in the browser:

      Large bold blue headline followed by an ordered list of seven items in black text, alternating background between pink and light blue with the fourth item having a purple background with white text.

      Note: The :nth-child() pseudo-class is able to also use algebric equations, such as 3n to select every third item in a list. CSS Tricks has a nth-child testing tool to test nth-child values to help understand the complex versatility of this pseudo-class selector.

      In this last section, you used the :nth-child() pseudo-class selector to apply styles to even-numbered elements, odd-numbered elements, and specifically the fourth element in the list.

      Conclusion

      In this tutorial, you have used many new selectors based on the concept of relationships. You used the descendant combinator and child combinator selectors to select elements inside other elements. Then, you used the general sibling combinator and adjacent sibling combinator to select elements that have a shared parent and apply styles based on proximity. Lastly, you used a series of pseudo-class selectors to style the first, last, and only child elements, along with every nth element in between. These selectors will help you hone and scope the styles of your projects.

      If you would like to read more CSS tutorials, try out the other tutorials in the How To Style HTML with CSS series.



      Source link