One place for hosting & domains

      How To Select HTML Elements Using ID, Class, and Attribute Selectors in CSS


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

      Introduction

      Writing CSS selectors most often involves setting a condition and locating the element in the HTML that fulfills that condition as true. You can do this broadly with an element selector to select high-level tags, but to gain more control over the selected elements, you can create specific identifiers in the HTML and apply them in the CSS.

      In this tutorial, you will use the id, class, and attribute selectors to scope styles to intentionally written HTML. You will begin by creating an HTML and a CSS file that you will edit throughout the tutorial. You will then add id attributes and use those id values to target styles. You will also add class attributes to elements and use those class values independently and together to create more specific and reusable styles. Lastly, you will use the attribute selector to create styles that match much more specific scenarios than an id or class selector alone can accomplish.

      Prerequisites

      Setting Up the Base HTML and CSS

      To start working with id, class, and attribute selectors, you will first set up the HTML and CSS code that you will work on through the rest of the tutorial. In this section, you will write out all the necessary HTML and some initial CSS styles that will handle layout and start the visual aesthetic.

      To begin, open 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 add a <meta> tag defining how mobile devices should render the page, set the title of 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>About CSS 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>Link and Buttons with State</title>
          <link rel="stylesheet" href="https://www.digitalocean.com/community/tutorials/styles.css">
        </head>
        <body>
          <header>
            <h1>Using CSS Selectors</h1>
          </header>
      
          <main>
            <section>
              <h2>Selecting HTML To Style</h2>
              <p>Selecting the right element and providing the right visual styles is the basis of <a href="https://do.co/community">writing CSS</a> code. Whenever you need to adjust how an element on a webpage looks, using selectors is key.</p>
              <p><a href="https://example.com">Read this to learn more about selectors</a></p>
            </section>
      
            <section>
              <h2>The Type Selector</h2>
              <p>The type selector finds elements on the page by tag name. This is a common way to style elements on the page. Type selectors are often referred to as element selectors.</p>
            </section>
      
            <section>
              <h2>Combining Selectors</h2>
              <p>A combinator selector is defined by a space character between selectors, with the HTML ancestry reading left to right. The right-most selector is the intended target. This can be as complex or as simple as necessary to <em>scope</em>, or provide sufficient specificity, to the intended element.</p>
            </section>
          </main>
        </body>
      </html>
      

      Save your changes to index.html and leave it open in your text editor. Open up your browser and load index.html to render the content of the page with the browser default styles. The following image shows these default styles with black serif text on a white background:

      Black serif text in various sizes with two blue, underlined links.

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

      styles.css

      body {
        font-family: sans-serif;
        line-height: 1.5;
        color: #444;
      }
      

      This CSS uses a body type selector to set the default font-family for the page to the browser’s sans-serif font. Then it changes the spacing between lines of text to 1.5 times the font-size. Lastly, the color value changes the text to a dark grey, instead of the default black.

      Save these changes to styles.css and return to the browser to see how these changes will appear, as shown in the following image:

      Dark gray sans-serif text in various sizes with two blue links with underlines.

      You have now set up the starting points for your index.html and your styles.css. In the next section, you will add an id attribute to elements in the HTML and create id selectors in the CSS to apply styles to those elements.

      Using the ID Selector

      In this section, you will learn about the id attribute and its purpose, then add several id attributes to your HTML. Finally, you will use some of these id selectors to apply layout styles.

      The id attribute is a unique identifier that links together content on the page. For example, say there is an element midway down the content of a web page with an id attribute of my-id. By appending that id value with a pound or hash symbol (#) to the URL, such as http://example.com/index.html#my-id, the browser will scroll to that section of the page. Since this can be used as part of the URL and for other scripting purposes, each id value on a page must be unique.

      To begin working with the id attribute, open index.html in your text editor. First, locate the <header> element and give it an id attribute with the value of header. Next, move to the <main> element and give it an id attribute with a value of content. These id attributes provide a unique identifier for the two primary sections of the content. The highlighted additions in the following code block show the changes you will make to your index.html file:

      index.html

      ...
      <header id="header">
        ...
      </header>
      <main id="content">
        ...
      </main>
      ...
      

      Note that well-written HTML will only have one <header> element and one <main> element, so it may seem redundant to assign a unique ID to elements that are already unique. However, applying specific IDs like this can separate your styling from your HTML structure, allowing you to retain consistent styling attached to the IDs even if the underlying HTML changes.

      Be sure to save your changes to index.html before continuing.

      The id selector in CSS uses the same format as when referenced in a URL: a pound sign followed by the name of the id, such as #my-id. To begin using the id selector, open styles.css in your text editor. Then, add the two id attribute values from your index.html as the group combinator #header, #content. You will use this selector to set the content of the <header> and the <main> element uniformly in the middle of the page. The following code block has the selector block and the code necessary for this layout:

      styles.css

      body {
        font-family: sans-serif;
        line-height: 1.5;
        color: #444;
      }
      
      #header,
      #content {
        margin: 1em auto;
        width: 90%;
        max-width: 60ch;
      }
      

      The id selectors will apply a margin of 1em to the top and bottom of both the <header> and the <main> element. The auto value on the margin property keeps the content centered to the page when paired with the width property of 90%. Lastly, the max-width property stops both containers from growing any wider once they reach a size of 60ch, which is equivalent to 60 0 characters in width.

      Save your changes to styles.css then open index.html in your browser. The contents of the page are now centered to the page instead of stretching across the length of the window. The following image illustrates how this appears in the browser:

      Text content centered to roughly half the width of the full size.

      In this section, you learned about the id attribute and used this attribute to apply styles to elements. You also learned that the id attribute is required to have a unique value because of how it can be used by the browser in URLs and in scripting. Next, you will use the class attribute to refactor the code from this section to apply colors to the content with new classes.

      Using the Class Selector

      In this section, you will use the class selector to find specific element on a page using values found in the class HTML attribute. You will refactor the id selectors to use a reusable class instead. The class attribute is meant to create a specific targetable value that styles can be applied to. Unlike the id, the values of class attributes can be reused, which is its advantage over the id selector.

      To begin styling elements with class, start by opening the index.html file in your text editor. On both the <header> and <main> elements, add a class attribute with a value of content-width. The highlighted section of the following code block indicates how to add the class attribute:

      index.html

      ...
      <header id="header" class="content-width">
        ...
      </header>
      <main id="content" class="content-width">
        ...
      </main>
      ...
      

      Save the changes to index.html, then open styles.css in your text editor to create the class selector for this class value.

      The class selector is similar to id in that it has a special character in CSS, which is indicated by the period symbol (.). In the styles.css file, locate the selector with the IDs #header, #content and replace both selectors with the .content-width class selector. The following highlighted code indicates the change you will make in your code:

      styles.css

      body {
        font-family: sans-serif;
        line-height: 1.5;
        color: #444;
      }
      
      .content-width {
        margin: 1em auto;
        width: 90%;
        max-width: 60ch;
      }
      

      Save these change to your styles.css and return to your browser. Refresh index.html and the styles will remain unchanged. The refactor to the code didn’t change the styles, but did change how the elements are selected. The versatility of a class is that the styles can be used more than once and on different element types.

      Next, return to index.html in your text editor and add a class attribute to the <h1> element with a value of style-1. This defines a class name that will be used in your CSS. The following code block indicates this change in the highlighted section:

      index.html

      ...
      <header id="header" class="content-width">
        <h1 class="style-1">Using CSS Selectors</h1>
      </header>
      ...
      

      Next, on each of the <h2> elements within the <main> element, add a class attribute. Give all three of these class attributes the value of style-2. Use the highlighted sections of the following code block for reference:

      index.html

      ...
      <main id="content" class="content-width">
        <section> 
          <h2 class="style-2">Selecting HTML To Style</h2>
          ...
        </section>
      
        <section>
          <h2 class="style-2">The Type Selector</h2>
          ...
        </section>
      
        <section>
          <h2 class="style-2">Combining Selectors</h2>
          ...
        </section>
      </main>
      ...
      

      After adding the class attributes to the elements in the index.html file, be sure to save the changes. Then, open styles.css in your text editor and create a class selector for the style-1 class.

      Add to the end of the styles.css a selector called .style-1. The period tells the browser to look for a class attribute on the page with the name of style-1. Then create a selector block and add a font-size property with a value of 1.25rem, a text-transform property set to uppercase, and a letter-spacing property to put 0.125em space between the characters. The following code block indicates these additions in the highlighted sections:

      styles.css

      ...
      .content-width {
        margin: 1em auto;
        width: 90%;
        max-width: 60ch;
      }
      .style-1 {
        font-size: 1.25rem;
        text-transform: uppercase;
        letter-spacing: 0.125em;
      }
      

      Next, create another class selector, this time for the style-2 class. Be sure to add the period before the name of the class value. Then add to that selector a font-size property with a 2rem value and a font-weight property set to normal. Reference the highlighted code in the following code block:

      styles.css

      ...
      .style-1 {
        font-size: 1.25rem;
        text-transform: uppercase;
        letter-spacing: 0.125em;
      }
      
      .style-2 {
        font-size: 2rem;
        font-weight: normal;
      }
      

      Save your changes to styles.css and refresh the index.html file in your browser. The <h1> content will now be smaller and uppercased while the <h2> content will be a bit larger and no longer bold. The following screenshot showcases how these changes will appear in the browser:

      Text in dark gray with a heading text that is short bold and uppercase, with other heading text much larger and title cased.

      Classes are a powerful selector, as they can be reused and applied to any element on the page. This means you can swap where and how the style-1 and style-2 classes are used, and no changes need to be made to the CSS.

      To make this change, open index.html and change the class attribute value style-1 on the <h1> element to style-2. Afterward, change the style-2 values on the <h2> elements’ class attribute to style-1. Reference the highlighted sections of the following code block for these changes:

      index.html

      ...
      <header id="header" class="content-width">
        <h1 class="style-2">Using CSS Selectors</h1>
      </header>
      
      <main id="content" class="content-width">
        <section> 
          <h2 class="style-1">Selecting HTML To Style</h2>
          ...
        </section>
      
        <section>
          <h2 class="style-1">The Type Selector</h2>
          ...
        </section>
      
        <section>
          <h2 class="style-1">Combining Selectors</h2>
          ...
        </section>
      </main>
      ...
      

      Save these changes to styles.css, return to your browser, and reload index.html. The large, normal font weight of style-2 is now applied to the content in the <h1> element, and the shorter, uppercase styles of style-1 now apply to the section <h2> elements. The following image shows how this will appear in the browser:

      Text in dark gray with a large title case heading text with other heading text that is short bold and uppercase.

      In this section you used class selectors to refactor the id selectors from the previous section. You also created two new class selectors to apply font styles to the <h1> and <h2> heading elements and you swapped those class attribute values to change which elements received what styles. In the next, section you will continue working with class selectors by applying more than one class to an HTML element.

      Combining Class Selectors

      In this section, you will apply multiple class values to the same HTML element to combine the styles from more than one CSS class selector. The advantage of class over id is its reusability, as shown in the previous section. class selectors can also be combined to target more specific elements. The class selector is the most common and preferred CSS selector for this versatility and specificity in finding an element and applying styles.

      To begin, open your styles.css file in your text editor. Then add three new class selectors: .color-1, .color-2, and .color-3. Each of these three selectors will have a color property with similar HSL values that differ by increments of 50 on the hue spectrum. This will provide a color palette that you can apply to elements in the HTML. See the highlighted portions of the following code block for what to add to your CSS file:

      styles.css

      ...
      .style-2 {
        font-size: 2rem;
        font-weight: normal;
      }
      
      .color-1 {
        color: hsl(300, 70%, 40%);
      }
      
      .color-2 {
        color: hsl(250, 70%, 40%);
      }
      
      .color-3 {
        color: hsl(200, 70%, 40%);
      }
      

      Save your changes to styles.css, then open index.html in your text editor. You will now add a color to each of the three <h2> elements in the <main> block. For the first <h2>, add a space after style-1 and then add color-1. The space between each value in the class attribute indicates an additional class name that can be referenced from the CSS. Do the same for the other <h2> elements, except use the color-2 value for the second <h2> and color-3 for the third <h2>.

      The highlighted portions of the following code block show how to format the additional class values:

      index.html

      ...
      <main id="content" class="content-width">
        <section> 
          <h2 class="style-1 color-1">Selecting HTML To Style</h2>
          ...
        </section>
      
        <section>
          <h2 class="style-1 color-2">The Type Selector</h2>
          ...
        </section>
      
        <section>
          <h2 class="style-1 color-3">Combining Selectors</h2>
          ...
        </section>
      </main>
      ...
      

      Save your changes to index.html, return to your browser, and refresh the page. The three <h2> section headings retain the same font styles, but now each have a different color. The following image shows how this will appear in your browser:

      Three short bold uppercase headings with one magenta, one dark blue, and one teal.

      Just as class values can be used together in HTML, the class names can also be combined to create more specific situations that may be present in the HTML. By chaining together class names in the CSS, you can select elements that have both classes at the same time.

      For example, the CSS selector .color-1.color-2 would only select elements that have an HTML class value that contains both color-1 and color-2.

      To try using multiple class names in a selector, open styles.css in your text editor. Create a new selector that combines the color-1 class and the color-2 class. The intent with this combination is to apply a color that is halfway between the defined color value of each of these classes.

      Add the following highlighted sections to your CSS file:

      styles.css

      ...
      .color-3 {
        color: hsl(200, 70%, 40%);
      }
      
      .color-1.color-2 {
        color: hsl(275, 70%, 40%);
      }
      
      .color-2.color-3 {
        color: hsl(225, 70%, 40%);
      }
      

      In this code block, you set the color property of the combined class selector .color1.color-2 to hsl(275, 70%, 40%), since that is halfway between the 300 value of .color-1 and the 250 value of .color-2. Then you did the same to combine .color-2 and .color-3.

      Be sure to save your changes to styles.css, then move over to index.html in your text editor and make the highlighted changes in the following code block:

      index.html

      ...
      <main id="content" class="content-width">
        <section> 
          <h2 class="style-1 color-1 color-2">Selecting HTML To Style</h2>
          ...
        </section>
        ...
        <section>
          <h2 class="style-1 color-3 color-2">Combining Selectors</h2>
          ...
        </section>
      </main>
      ...
      

      Note that the new styling you declared for the combined class selectors will take precedence over the style set for each of the individual classes. This is because the combined class selector is selecting a more specific element than the individual class selectors. For example, the rule you wrote for .color-1 is looking for an HTML element that has color-1 as one of its classes. The .color-1.color-2 rule is looking for an HTML element that has both color-1 and color-2 in the list of its classes. Since the second rule is a subset of the first, it can be said to be more specific, and thus overrides the first.

      With the two combined class CSS rules you have written, there are situations in which both rules could apply. For example, an HTML element with a class value of color-1 color-2 color-3 would satisfy both the .color-1.color-2 and .color-2.color-3 rules. In this case, since they both have the same amount of specificity, the cascade would come into effect, and the last rule declared would override the styling. In this case, .color-2.color-3 would apply its styling, since it is the final rule declared.

      Save the changes to index.html and then refresh the page in your browser. The colors of all three <h2> elements will still be distinct, but will now be visually closer together in hue.

      The following screenshot shows how this will appear in the browser:

      Three short bold uppercase headings with one purple, one dark blue, and one a medium blue.

      This section presented you with a way to string class values together to create more specific scenarios in which to apply styles. In the next section, you will learn how to find an element on the page based on any attribute type.

      Using the Attribute Selector

      In this section, you will use the attribute selector to find and select an element. In the previous sections, you have learned that the id and class selectors have a symbol indicating the kind of attribute to target followed by a value to select. The attribute selector’s format consists of the name of the attribute wrapped in a pair of square brackets, like so: [attr]. The attribute selector can be used with any attribute, including id and class.

      To begin using an attribute selector, open the index.html file in your text editor. You will add the HTML element for abbreviations, <abbr>, as a situation where attribute selectors would be beneficial. Place the <abbr> around the first instance of CSS in the <h1> element. Then, place another <abbr> around the first instance of HTML in the first <h2> element. With the HTML <abbr>, add a title attribute with a value of Hypertext Markup Language. Reference the following code block for how this will be formatted:

      index.html

      ...
      <h1 class="style-2">Using <abbr>CSS</abbr> Selectors</h1>
      ...
      <h2 class="style-1 color-1 color-2">Selecting <abbr title="Hypertext Markup Language">HTML</abbr> To Style</h2>
      ...
      

      Save your changes to index.html, then return to your browser to load the file. If you are using Chrome or Firefox, the browser default for <abbr> elements with a title attribute is to add a dotted underline. The purpose of the visual indicator is to have a user hover over the text, at which point the meaning of the abbreviation, the title attribute’s value, will appear. The following image demonstrates the default <abbr> styling in Firefox:

      Short bold uppercase headings in purple with an abbreviation text with a dotted underline.

      Unlike Chrome and Firefox, some browsers, like Safari and other older browsers, do not have an indicator of when an <abbr> element has a title. This same styling can be brought to these other browsers, along with some customizations with the attribute selector.

      To begin styling with an attribute selector, open the styles.css file in your text editor. Add an attribute selector for How To Select HTML Elements Using ID, Class, and Attribute Selectors in CSS and then curly brackets for the selector block. In the selector block, add the text-decoration property set to underline. Then add the text-decoration-style property with a value of dotted. These two properties will equalize the styling across browsers. Lastly, to add a custom look for the underline, add the property text-decoration-color and set it to a light gray with the value hsl(0, 0%, 70%).

      Reference the following code block for how this will be formatted in your code:

      styles.css

      ...
      .color-2.color-3 {
        color: hsl(225, 70%, 40%);
      }
      
      How To Select HTML Elements Using ID, Class, and Attribute Selectors in CSS {
        text-decoration: underline;
        text-decoration-style: dotted;
        text-decoration-color: hsl(0, 0%, 70%);
      }
      

      Save your changes to styles.css, then return to your browser and refresh index.html. The styling for the HTML text will now have a light gray dotted underline. The following image demonstrates how this will appear in the browser:

      Short bold uppercase headings in purple with an abbreviation text with a light gray dotted underline.

      The one issue with using the How To Select HTML Elements Using ID, Class, and Attribute Selectors in CSS attribute as a selector is that it can be used on almost any element on the page. This means, with the current selector in place, <img> or <a> elements with the title attribute would also receive these styles. In this case, the selector needs to be scoped to work only with the <abbr> element.

      To make this adjustment to the selector, return to styles.css in your text editor. To the left of the How To Select HTML Elements Using ID, Class, and Attribute Selectors in CSS attribute selector, add the abbr element selector. Be sure there is no space between these selectors as this tells the browser to specifically look for an <abbr> element with a title attribute. The following code block demonstrates how this will look, with the added element selector highlighted:

      styles.css

      ...
      abbrHow To Select HTML Elements Using ID, Class, and Attribute Selectors in CSS {
        text-decoration: underline;
        text-decoration-style: dotted;
        text-decoration-color: hsl(0, 0%, 70%);
      }
      

      Save your changes to styles.css. The styles are now scoped to only work with <abbr> elements with a title attribute. The CSS <abbr> in the <h1> element will not receive these styles either. Though it does match the abbr selector, it does not have a title attribute and so does not match.

      In this section, you used the attribute selector to scope styles to an <abbr> element to apply styles when a title attribute is present. In the next section, you will use more advanced capabilities of the attribute selector by matching the value of a given attribute.

      Creating Advanced Attribute Selectors

      The attribute selector is useful for finding particular attributes in the HTML and applying styles to them. However, the attribute selector also has several ways to look for the value of an attribute. In this final section, you will use the attribute selector to look for matching value strings and apply styles that meet these specific conditions.

      To begin, open your styles.css file in the text editor. In the HTML there is a link that goes to the website https://example.com; to target that specific URL link, create an attribute selector for an href attribute. Then, within the brackets following the attribute name, add an equal sign followed by string quotes. Within those quotes, add https://example.com. This selector will target a link that goes to the specified URL. Add a color property with a green color using hsl(150, 70%, 40%).

      The highlighted code in the following code block shows how this is formatted in your styles.css file:

      styles.css

      ...
      abbrHow To Select HTML Elements Using ID, Class, and Attribute Selectors in CSS {
        text-decoration: underline;
        text-decoration-style: dotted;
        text-decoration-color: hsl(0, 0%, 70%);
      }
      
      [href="https://example.com"] {
        color: hsl(150, 70%, 40%);
      }
      

      Save these changes to styles.css and return to your browser to refresh index.html. Only the link that goes to https://example.com has changed to the color green, while the other link on the page remains the default blue. The following image demonstrates how this will appear in the browser:

      Link text in green color with underline.

      Next, return to styles.css in your text editor and add a custom hover state by using the :hover pseudo selector. The selector is set up the same as the previous selector, and immediately follows after the closing square bracket with :hover. Then within the selector add a color property with a darkened version of the previous green by changing the lightness value of the HSL from 40% to 20%.

      Reference the highlighted code in the following code block for how to format this in your code:

      styles.css

      ...
      [href="https://example.com"] {
        color: hsl(150, 70%, 40%); 
      }
      
      [href="https://example.com"]:hover {
        color: hsl(150, 70%, 20%);
      }
      

      Save your changes to styles.css and then reload index.html in your browser. The link that goes to https://example.com now has a hover state that switches to a darker green, as demonstrated in the following animation:

      Animation of green text link with underline changing to dark green when cursor hovers text.

      The attribute selector has additional condition modifiers to look for particular scenarios within a value string. One of these conditions that an attribute can look for is if a value starts with a given string. This is represented with the ^ symbol between the attribute name and the equal sign. This approach can be used to highlight links that are secure, meaning they go to a URL that begins with https:// instead of http://.

      Return to styles.css in your text editor and add an attribute selector that looks for a value that begins with a secure URL by using [href^="https://"]. This selector will only match elements that have an href element that begins with https://. Then, to add a visual indicator that the link is secure, use a pseudo element selector by adding ::before immediately following the closing bracket. Lastly, the ::before pseudo element selector requires a content property to be used, which will add a string before the content of the HTML element. For the value of this content property, use the unicode identifier for the lock emoji, 1F512.

      The highlighted section of the following code block demonstrates this syntax:

      styles.css

      ...
      
      [href^="https://"]::before {
        content: '1F512';
      }
      

      Save your changes to styles.css and return to your web browser to reload index.html. The two links in the content both have secure links and are now indicated as such with the lock emoji, as demonstrated in the following image:

      Links in two different styles with lock emoji preceding the link text.

      In this section you used the advanced features of the attribute selector to look for specific strings in the HTML attribute’s value. There are more options available for attribute value scenarios than were covered here. If you want to learn more about the different attribute selector options, read The Skinny on CSS Attribute Selectors by Chris Coyier.

      Conclusion

      Writing styles that are specific and reusable is a cornerstone to effective CSS architecture. In this tutorial, you learned how and when to use the id selector, how you can use and reuse the class selector in multiple combinations, and how to use the attribute selector and some of its features to create very specific scenarios in which to add styling. These selectors are a powerful asset to create styles that bring life and functionality to a website.

      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 Deploy a Static HTML Website with Ansible on Ubuntu 20.04 (Nginx)



      Part of the Series:
      How To Write Ansible Playbooks

      Ansible is a modern configuration management tool that doesn’t require the use of an agent software on remote nodes, using only SSH and Python to communicate and execute commands on managed servers. This series will walk you through the main Ansible features that you can use to write playbooks for server automation. At the end, we’ll see a practical example of how to create a playbook to automate setting up a remote Nginx web server and deploy a static HTML website to it.

      If you were following along with all parts of this series, at this point you should be familiar with installing system packages, applying templates, and using handlers in Ansible playbooks. In this part of the series, you’ll use what you’ve seen so far to create a playbook that automates setting up a remote Nginx server to host a static HTML website on Ubuntu 20.04.

      Start by creating a new directory on your Ansible control node where you’ll set up the Ansible files and a demo static HTML website to be deployed to your remote server. This could be in any location of your choice within your home folder. In this example we’ll use ~/ansible-nginx-demo.

      • mkdir ~/ansible-nginx-demo
      • cd ~/ansible-nginx-demo

      Next, copy your existing inventory file into the new directory. In this example, we’ll use the same inventory you set up at the beginning of this series:

      • cp ~/ansible-practice/inventory .

      This will copy a file named inventory from a folder named ansible-practice in your home directory, and save it to the current directory.

      Obtaining the Demo Website

      For this demonstration, we’ll use a static HTML website that is the subject of our How To Code in HTML series. Start by downloading the demo website files by running the following command:

      • curl -L https://github.com/do-community/html_demo_site/archive/refs/heads/main.zip -o html_demo.zip

      You’ll need unzip to unpack the contents of this download. To make sure you have this tool installed, run:

      Then, unpack the demo website files with:

      This will create a new directory called html_demo_site-main on your current working directory. You can check the contents of the directory with an ls -la command:

      • ls -la html_demo_site-main

      Output

      total 28 drwxrwxr-x 3 sammy sammy 4096 sep 18 2020 . drwxrwxr-x 5 sammy sammy 4096 mrt 25 15:03 .. -rw-rw-r-- 1 sammy sammy 1289 sep 18 2020 about.html drwxrwxr-x 2 sammy sammy 4096 sep 18 2020 images -rw-rw-r-- 1 sammy sammy 2455 sep 18 2020 index.html -rw-rw-r-- 1 sammy sammy 1079 sep 18 2020 LICENSE -rw-rw-r-- 1 sammy sammy 675 sep 18 2020 README.md

      Creating a Template for Nginx’s Configuration

      You’ll now set up the Nginx template that is necessary to configure the remote web server. Create a new folder within your ansible-demo directory to hold non-playbook files:

      Then, open a new file called nginx.conf.j2:

      This template file contains an Nginx server block configuration for a static HTML website. It uses three variables: document_root, app_root, and server_name. We’ll define these variables later on when creating the playbook. Copy the following content to your template file:

      ~/ansible-nginx-demo/files/nginx.conf.j2

      server {
        listen 80;
      
        root {{ document_root }}/{{ app_root }};
        index index.html index.htm;
      
        server_name {{ server_name }};
      
        location / {
         default_type "text/html";
         try_files $uri.html $uri $uri/ =404;
        }
      }
      

      Save and close the file when you’re done.

      Creating a New Ansible Playbook

      Next, we’ll create a new Ansible playbook and set up the variables that we’ve used in the previous section of this guide. Open a new file named playbook.yml:

      This playbook starts with the hosts definition set to all and a become directive that tells Ansible to run all tasks as the root user by default (the same as manually running commands with sudo). Within this playbook’s var section, we’ll create three variables: server_name, document_root, and app_root. These variables are used in the Nginx configuration template to set up the domain name or IP address that this web server will respond to, and the full path to where the website files are located on the server. For this demo, we’ll use the ansible_default_ipv4.address fact variable because it contains the remote server’s public IP address, but you can replace this value with your server’s hostname in case it has a domain name properly configured within a DNS service to point to this server:

      ~/ansible-nginx-demo/playbook.yml

      ---
      - hosts: all
        become: yes
        vars:
          server_name: "{{ ansible_default_ipv4.address }}"
          document_root: /var/www/html
          app_root: html_demo_site-main
        tasks:
      

      You can keep this file open for now. The next sections will walk you through all tasks that you’ll need to include in this playbook to make it fully functional.

      Installing Required Packages

      The following task will update the apt cache and then install the nginx package on remote nodes:

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Update apt cache and install Nginx
            apt:
              name: nginx
              state: latest
              update_cache: yes
      

      Uploading Website Files to Remote Nodes

      The next task will use the copy built-in module to upload the website files to the remote document root. We’ll use the document_root variable to set the destination on the server where the application folder should be created.

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Copy website files to the server's document root
            copy:
              src: "{{ app_root }}"
              dest: "{{ document_root }}"
              mode: preserve
      

      Applying and Enabling the Custom Nginx Configuration

      We’ll now apply the Nginx template that will configure the web server to host your static HTML file. After the configuration file is set at /etc/nginx/sites-available, we’ll create a symbolic link to that file inside /etc/nginx-sites-enabled and notify the Nginx service for a posterior restart. The entire process will require two separate tasks:

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Apply Nginx template
            template:
              src: files/nginx.conf.j2
              dest: /etc/nginx/sites-available/default
            notify: Restart Nginx
      
          - name: Enable new site
            file:
              src: /etc/nginx/sites-available/default
              dest: /etc/nginx/sites-enabled/default
              state: link
            notify: Restart Nginx
      

      Allowing Port 80 on UFW

      Next, include the task that enables tcp access on port 80:

      ~/ansible-nginx-demo/playbook.yml

      . . .
          - name: Allow all access to tcp port 80
            ufw:
              rule: allow
              port: '80'
              proto: tcp
      . . .
      

      Creating a Handler for the Nginx Service

      To finish this playbook, the only thing left to do is to set up the Restart Nginx handler:

      ~/ansible-nginx-demo/playbook.yml

      . . .
        handlers:
          - name: Restart Nginx
            service:
              name: nginx
              state: restarted  
      

      Running the Finished Playbook

      Once you’re finished including all the required tasks in your playbook file, it will look like this:

      ~/ansible-nginx-demo/playbook.yml

      ---
      - hosts: all
        become: yes
        vars:
          server_name: "{{ ansible_default_ipv4.address }}"
          document_root: /var/www
          app_root: html_demo_site-main
        tasks:
          - name: Update apt cache and install Nginx
            apt:
              name: nginx
              state: latest
              update_cache: yes
      
          - name: Copy website files to the server's document root
            copy:
              src: "{{ app_root }}"
              dest: "{{ document_root }}"
              mode: preserve
      
          - name: Apply Nginx template
            template:
              src: files/nginx.conf.j2
              dest: /etc/nginx/sites-available/default
            notify: Restart Nginx
      
          - name: Enable new site
            file:
              src: /etc/nginx/sites-available/default
              dest: /etc/nginx/sites-enabled/default
              state: link
            notify: Restart Nginx
      
          - name: Allow all access to tcp port 80
            ufw:
              rule: allow
              port: '80'
              proto: tcp
      
        handlers:
          - name: Restart Nginx
            service:
              name: nginx
              state: restarted
      

      To execute this playbook on the server(s) that you set up in your inventory file, run ansible-playbook with the same connection arguments you’ve used when running a connection test within the introduction of this series. Here, we’ll be using an inventory file named inventory and the sammy user to connect to the remote server. Because the playbook requires sudo to run, we’re also including the -K argument to provide the remote user’s sudo password when prompted by Ansible:

      • ansible-playbook -i inventory playbook.yml -u sammy -K

      You’ll see output like this:

      Output

      BECOME password: PLAY [all] ********************************************************************************************** TASK [Gathering Facts] ********************************************************************************** ok: [203.0.113.10] TASK [Update apt cache and install Nginx] *************************************************************** ok: [203.0.113.10] TASK [Copy website files to the server's document root] ************************************************* changed: [203.0.113.10] TASK [Apply Nginx template] ***************************************************************************** changed: [203.0.113.10] TASK [Enable new site] ********************************************************************************** ok: [203.0.113.10] TASK [Allow all access to tcp port 80] ****************************************************************** ok: [203.0.113.10] RUNNING HANDLER [Restart Nginx] ************************************************************************* changed: [203.0.113.10] PLAY RECAP ********************************************************************************************** 203.0.113.10 : ok=7 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

      Once the playbook is finished, if you go to your browser and access your server’s hostname or IP address you should now see the following page:

      HTML Demo Site Deployed by Ansible

      Congratulations, you have successfully automated the deployment of a static HTML website to a remote Nginx server, using Ansible.

      If you make changes to any of the files in the demo website, you can run the playbook again and the copy task will make sure any file changes are reflected in the remote host. Because Ansible has an idempotent behavior, running the playbook multiple times will not trigger changes that were already made to the system.



      Source link

      How To Use Python-Markdown to Convert Markdown Text to HTML


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Markdown is a markup language commonly used to simplify the process of writing content in an easy-to-read text format, which a software tool or programming library can convert into HTML to display in a browser or another writing program. Because it uses plain-text syntax, Markdown is compatible with any text editor and can convert headings, lists, links, and other components. Bloggers, tutorial authors, and documentation writers use Markdown widely and websites, such as Github, StackOverflow, and The Python Package Index (PyPI), support it.

      You can learn how to use Markdown from the Markdown syntax standard. Alternatively, you can also try a different Markdown implementation in a web editor, like the DigitalOcean Markdown Preview or the StackEdit editor.

      Python-Markdown is a Python library that allows you to convert Markdown text to HTML in various ways. You can extend its functionality using its different extensions that provide additional features. Note however, that the Python-Markdown has a few minor differences with the standard Markdown syntax.

      In this tutorial, you will install the Python-Markdown library, use it to convert Markdown strings to HTML, convert Markdown files to HTML files, and use the Python-Markdown command line interface to convert Markdown to HTML.

      Prerequisites

      Before you start following this guide, you will need:

      Step 1 — Installing Python-Markdown

      In this step, you will install Python-Markdown and explore one of its functions to convert Markdown strings to HTML in the Python REPL.

      If you haven’t already activated your programming environment, make sure you’re in your project directory (pymark) and use the following command to activate the environment:

      Once you have activated your programming environment, your prompt will now have an env prefix like the following:

      Now you’ll install Python packages and isolate your project code away from the main Python system installation.

      Use pip to install the Python-Markdown library (markdown) by running the following command:

      Once the installation finishes successfully, you can experiment with it in the Python REPL, which you can open by typing the following command:

      You will notice a new prompt with the prefix >>>; you can use this to type in Python code and receive immediate output.

      First you will import the markdown package and use it to convert a piece of Markdown text from Markdown syntax to HTML:

      • import markdown
      • markdown.markdown('#Hi')

      In this code, you import the markdown package you installed earlier. You use the markdown.markdown() function to convert the Markdown text #Hi (with # representing an H1-level header) to its HTML equivalent. If you type the code into the Python REPL, you will receive the following output:

      Output

      '<h1>Hi</h1>'

      The HTML output is the equivalent of the #Hi Markdown text.

      You can use triple single quotes (''') to type multi-line Markdown text into the Python REPL like so:

      • import markdown
      • output = markdown.markdown('''
      • # Step 1
      • ## Step 2
      • * item 1
      • * item 2
      • Visit [the tutorials page](https://www.digitalocean.com/community/tutorials) for more tutorials!
      • ''')
      • print(output)

      In this example, you pass an H1 header, an H2 header, two list items, and a paragraph containing a link. You then save the output in a variable called output and print it with the print() Python function.

      You will receive the following output:

      Output

      <h1>Step 1</h1> <h2>Step 2</h2> <ul> <li>item 1</li> <li>item 2</li> </ul> <p>Visit <a href="https://www.digitalocean.com/community/tutorials">the tutorials page</a> for more tutorials!</p>

      You’ll notice that the output results in the HTML version of the provided Markdown text.

      Now that you’ve used the markdown package to convert Markdown text to HTML, you will make a small program to read and convert Markdown files to HTML files.

      Step 2 — Creating a Program to Convert Markdown Files to HTML

      In this step, you will create a Python program that reads a Markdown file, converts its contents to HTML using the markdown.markdown() function, and saves the HTML code in a new file.

      First, open a new file called Picnic.md to hold the Markdown text:

      Type the following Markdown text into it:

      pymark/Picnic.md

      # Things to bring
      
      * Food.
      * Water.
      * Knife.
      * Plates.
      

      In this file you have an H1 header and four list items.

      Once you’re done, save and close the file.

      Next, open a new file called convert.py to hold the code for converting the Picnic.md Markdown file to an HTML file:

      Type the following Python code into it:

      pymark/convert.py

      import markdown
      
      with open('Picnic.md', 'r') as f:
          text = f.read()
          html = markdown.markdown(text)
      
      with open('Picnic.html', 'w') as f:
          f.write(html)
      

      Here, you first import the markdown package. You use the open() function to open the Picnic.md file; passing the value 'r' to the mode parameter to signify that Python should open it for reading.

      You save the file object in a variable called f, which you can use to reference the file. Then you read the file and save its contents inside the text variable. After, you convert the text using markdown.markdown(), saving the result in a variable called html.

      With the same pattern, you open a new file called Picnic.html in writing mode ('w')—note that this file does not yet exist—and write the contents of the html variable to the file. This creates and saves the new file on your system. Using the with statement when opening a file guarantees that Python will close it once processing has finished.

      Save and close the file.

      Run the convert.py program:

      This creates a new file called Picnic.html in your project directory with the following contents:

      pymark/Picnic.html

      <h1>Things to bring</h1>
      <ul>
      <li>Food.</li>
      <li>Water.</li>
      <li>Knife.</li>
      <li>Plates.</li>
      </ul>
      

      Now that you know how to open and convert Markdown files using the markdown.markdown() function, you can generate Markdown text in Python and convert Markdown files without the need to read them first.

      Step 3 — Generating Markdown from Data and Converting it to HTML

      In this step, you will create a program that generates Markdown text from a Python dictionary, saves it to a Markdown file, and converts the Markdown text to an HTML file using the markdown.markdownFromFile() function.

      Your program will generate a Markdown file called cities.md with a list of countries and their top three largest cities. After, the program will convert the generated Markdown text into HTML, then it will save the HTML in a file called cities.html.

      First open a new Python file called citygen.py:

      Then add the following Python code:

      pymark/citygen.py

      import markdown
      
      
      country_cities = {'Japan': ['Tokyo', 'Osaka', 'Nagoya'],
                        'France': ['Paris', 'Marseille', 'Lyon'],
                        'Germany': ['Berlin', 'Hamburg', 'Munich'],
                        }
      

      In this code you first import the Python-Markdown library with import markdown. Then you define a country_cities dictionary containing a few countries as the keys and a list of the largest three cities for each country as the value. This dictionary is an example data structure; you can replace it with fetched data from a web API, a database, or any other data source.

      Next add the following code after your dictionary:

      pymark/citygen.py

      . . .
      with open('cities.md', 'bw+') as f:
          for country, cities in country_cities.items():
              f.write('# {}n'.format(country).encode('utf-8'))
              for city in cities:
                  f.write('* {}n'.format(city).encode('utf-8'))
          f.seek(0)
          markdown.markdownFromFile(input=f, output="cities.html")
      

      After constructing the dictionary that holds the data, you use the with open(...) as ... syntax to open a file called cities.md, which doesn’t exist yet. You open it in binary mode ('b') for writing and reading ('w+'). You use binary mode, because if you pass a string to markdown.markdownFromFile(), it will be interpreted as a path to a readable file on the file system (that is, '/home/file.md'). Also binary mode allows you to avoid issues related to converting characters to a platform-specific representation; this guarantees that the Python program will behave the same way on any platform.

      You then go through the dictionary’s items extracting each key that contains the country’s name and saving it in the country variable. Alongside this, you extract the value that represents the list of the country’s largest cities and save it in the cities variable.

      Inside the first loop, you write the country’s name to the new cities.md file in a # Markdown header (the <h1> HTML tag). n is a special character for inserting a new line. You use .encode() because you have opened the file in binary mode. The second for loop iterates through each city and writes its name to the Markdown file as a * list item (the <li> HTML tag).

      After the first loop finishes, you have moved to the end of the file, which means markdown.markdownFromFile() won’t be able to read its contents; therefore, you use f.seek(0) to go back to the top of the file. Before passing the f object to markdown.markdownFromFile() as input, to convert it to HTML and save it to a new file called cities.html.

      Once you’re done, save and close the file.

      Run the citygen.py program:

      This command will generate two files:

      • cities.md: A Markdown file with the following contents:

      pymark/cities.md

      # Japan
      * Tokyo
      * Osaka
      * Nagoya
      # France
      * Paris
      * Marseille
      * Lyon
      # Germany
      * Berlin
      * Hamburg
      * Munich
      
      • cities.html: An HTML file that contains the result of converting the contents of cities.md:

      pymark/cities.html

      <h1>Japan</h1>
      <ul>
      <li>Tokyo</li>
      <li>Osaka</li>
      <li>Nagoya</li>
      </ul>
      <h1>France</h1>
      <ul>
      <li>Paris</li>
      <li>Marseille</li>
      <li>Lyon</li>
      </ul>
      <h1>Germany</h1>
      <ul>
      <li>Berlin</li>
      <li>Hamburg</li>
      <li>Munich</li>
      </ul>
      

      You can also use the function markdown.markdownFromFile() to convert an existing Markdown file. For example, you can convert the Picnic.md file to a file called Picnic-out.html using the following code:

      example.py

      import markdown
      
      markdown.markdownFromFile(input="Picnic.md", output="Picnic-out.html")
      

      You can use the markdown.markdownFromFile() function to directly convert a file, if the file does not need any modification. If you do need to modify the Markdown file, you can read it, then convert it using the method demonstrated in Step 2.

      You’ve converted Markdown text to HTML in Python code, but Python-Markdown also provides a helpful command line interface (CLI) to quickly convert Markdown files to HTML—you’ll review this tool in the next step.

      Step 4 — Using Python-Markdown’s Command Line Interface

      In this step you will use Python-Markdown’s CLI to convert a Markdown file to HTML and print the output, or save it to an HTML file.

      You can run the Python-Markdown command line script using the -m flag supported by Python, which runs a library module as a script. For example, to convert a Markdown file, you can pass it to the markdown command as follows, replacing filename.md with the name of the file you want to convert:

      • python -m markdown filename.md

      Executing this command will print the HTML code for the Markdown text that’s present in the filename.md file.

      For example, to convert the Picnic.md file, run the following command:

      • python -m markdown Picnic.md

      This will print the following output:

      Output

      <h1>Things to bring</h1> <ul> <li>Food.</li> <li>Water.</li> <li>Knife.</li> <li>Plates.</li> </ul>

      To save the output to a file called output.html, use the following command:

      • python -m markdown Picnic.md -f output.html

      With this, you’ve now used the markdown command line interface to convert a Markdown file to HTML.

      Conclusion

      In this tutorial, you have used Python to convert Markdown text to HTML. You can now write your own Python programs that take advantage of the Markdown syntax in different contexts, such as web applications using a web framework like Flask or Django. For more on how to use Markdown, check out the Markdown website. For more information on using Markdown with Python, check out the Python-Markdown documentation.

      Here are a few extensions officially supported by Python-Markdown:

      • Extra: An extension that adds extra features to the standard Markdown syntax, such as defining abbreviations, adding attributes to various HTML elements, footnotes, tables, and other features.
      • CodeHilite: An extension that adds syntax highlighting to code blocks.
      • Table of Contents: An extension that generates a table of contents from a Markdown document and adds it into the resulting HTML document.



      Source link