ScreenshotNeo

BlogGuides

CSS3 Tutorial: Features, Selectors, and Examples

Learn how CSS rules and selectors work, compare common selector types, and build a complete responsive card example you can adapt.

By the ScreenshotNeo team4 October 202611 min read

CSS controls how structured documents such as HTML are presented: typography, color, spacing, layout, and more. A CSS rule uses a selector to choose elements and a declaration block to set property-value pairs. This tutorial explains the core features commonly associated with “CSS3,” shows how selectors match real HTML, and builds a responsive example you can run and adapt.

“CSS3” is a familiar umbrella term, not one final specification containing every modern CSS feature. CSS is developed in modules, and specification stability does not guarantee that a feature is implemented by every browser. Check support for the specific features you plan to use.

1. How CSS works

A browser parses HTML into a document tree, matches CSS selectors against elements in that tree, and resolves applicable declarations through the cascade. These are distinct steps: a selector determines which elements match; the cascade determines which declaration wins when multiple rules apply.

<p class="intro">CSS styles this paragraph.</p>
.intro {
  color: rebeccapurple;
  line-height: 1.5;
}

Here, .intro is the selector. The braces contain declarations. Each declaration has a property (color, line-height) and a value (rebeccapurple, 1.5).

Ways to add CSS

  • External stylesheet: Put rules in a .css file and link it from the HTML. This is usually the clearest choice for a site or multi-page project.
  • Internal stylesheet: Put rules in a <style> element in the document’s <head>. This can suit a small standalone page.
  • Inline style: Set a style attribute on an element. Use it sparingly; it is harder to maintain and can complicate overrides.
<!-- External stylesheet -->
<link rel="stylesheet" href="styles.css">

<!-- Internal stylesheet -->
<style>
  .note { color: #333; }
</style>

<!-- Inline style -->
<p style="color: #333">A paragraph</p>

2. Common CSS features

CSS lets you describe presentation in reusable rules. These examples use established properties and patterns; check browser support when you adopt newer features.

Area Example What it controls
Typography font-family, font-size, line-height How text looks and reads
Color and surfaces color, background-color, border-color Text, backgrounds, and borders
Spacing and sizing margin, padding, max-width Space around and inside elements and their dimensions
Layout Flexbox, Grid, positioning How elements are arranged
Responsive presentation Media queries and flexible sizing How a layout adapts to available space
Interaction states :hover, :focus, :checked Presentation based on an element’s state

Readable text and spacing

body {
  font-family: system-ui, sans-serif;
  color: #222;
  line-height: 1.6;
}

article {
  max-width: 70ch;
  margin-inline: auto;
  padding: 1rem;
}

Relative units such as rem and content-aware limits such as ch can help keep spacing and line lengths adaptable. Choose values based on the design and check the result at the sizes your page needs to support.

Layout and responsive rules

.card-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem;
}

@media (max-width: 40rem) {
  .page-header {
    padding: 1rem;
  }
}

The grid definition lays out cards in columns that fit the available space, with a minimum column size. The media query applies its declarations when the viewport meets the written condition. Responsive design is about matching the layout to the available space; select breakpoints based on where the content needs them.

3. CSS selectors and what they match

Selectors can target elements by type, class, ID, attribute, state, or position. The examples below show each selector with the corresponding HTML context.

Selector Matches Example use
p Every paragraph element Base text styling
.notice Elements whose class list includes notice A reusable notice style
#main-content An element with the ID value main-content A specific document section
input[type="email"] Email inputs Style an input by attribute value
a:hover Links while in the hover state Pointer interaction feedback
li:first-child A list item that is first among its siblings Style by structural position
<main id="main-content">
  <p class="notice">Read the instructions.</p>
  <label>Email
    <input type="email" name="email">
  </label>
  <nav><a href="/docs">Documentation</a></nav>
</main>
p { color: #333; }
.notice { padding: 1rem; background-color: #f1f5f9; }
#main-content { max-width: 70ch; margin-inline: auto; }
input[type="email"] { border: 1px solid teal; }
a:hover { text-decoration: underline; }
li:first-child { font-weight: 700; }

Type, class, and ID selectors

  • Type selector: p matches paragraph elements. It is useful for broad defaults.
  • Class selector: .notice matches elements carrying the notice class. Classes are reusable across elements and are a common choice for component styling.
  • ID selector: #main-content matches an element by its ID value. An ID identifies a particular element in the document; avoid relying on duplicated IDs or using IDs as the default for reusable styling.

In HTML, class values can contain multiple space-separated names, so one element can match multiple class selectors. An ID selector matches the ID value, not a class that happens to have the same text.

Attribute and pseudo-class selectors

An attribute selector tests an element’s attributes. For example, [type="email"] matches an input with that exact attribute value. Pseudo-classes select elements based on state or structural conditions: :hover describes pointer hover, while :first-child describes position among siblings. Use keyboard-visible states such as :focus as part of accessible interaction styling.

input[required] { border-inline-start: 3px solid #b42318; }
a:focus { outline: 3px solid #2563eb; outline-offset: 2px; }
li:nth-child(odd) { background-color: #f8fafc; }

Combinators: matching relationships

Combinators let a selector express a relationship in the document tree:

  • A B (space), descendant: matches a B anywhere inside an A.
  • A > B, child: matches a B that is a direct child of an A.
  • A + B, adjacent sibling: matches a B immediately after an A, with the same parent.
  • A ~ B, subsequent sibling: matches a B that follows an A and shares its parent.
article p { line-height: 1.6; } /* Any paragraph inside article */
nav > a { margin-inline-end: 1rem; } /* Direct child links only */
h2 + p { margin-block-start: 0; } /* Paragraph immediately after h2 */
h2 ~ p { color: #444; } /* Later paragraph siblings */

Choose the narrowest relationship that reflects the intended structure. A deeply nested selector can become fragile if the HTML changes.

4. Specificity, the cascade, and selector choice

When several matching rules set the same property, the browser resolves the conflict through the cascade. Specificity is one part of that process; source order and other cascade rules also matter. A practical selector choice should consider what matches, whether the rule is reusable, how much it depends on document structure, and how difficult it will be to override.

p { color: #333; }
.notice { color: #8a3412; }
#main-content .notice { color: #7c2d12; }

For a paragraph carrying notice inside #main-content, all three selectors can match. Their declarations compete, and the cascade resolves which color applies. Prefer simple, purposeful selectors so later maintenance does not require increasingly specific overrides. Avoid using !important as a routine way to win conflicts; first find the rule and cascade layer responsible.

Need Good starting point Watch for
Style a reusable component A class such as .notice Keep the class name tied to a meaningful role
Set a broad element default A type selector such as p It affects every matching element in scope
Target a control by kind An attribute selector Confirm the attribute and value in the rendered HTML
Style an interaction state A pseudo-class such as :focus Consider keyboard as well as pointer interaction
Target a structural relationship A combinator Structural changes can alter which elements match

5. Complete runnable example: responsive article cards

Save the following as index.html and open it in a browser. The stylesheet is embedded so the example runs as one file. It demonstrates a type selector, classes, an ID, an attribute selector, pseudo-classes, Grid, and a media query.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>CSS selector tutorial</title>
  <style>
    * { box-sizing: border-box; }
    body {
      margin: 0;
      font-family: system-ui, sans-serif;
      line-height: 1.55;
      color: #172033;
      background: #f5f7fb;
    }
    #page {
      width: min(100% - 2rem, 64rem);
      margin-inline: auto;
      padding-block: 2rem;
    }
    .intro { max-width: 65ch; }
    .card-list {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
      gap: 1rem;
      margin-block: 1.5rem;
    }
    .card {
      padding: 1.25rem;
      border: 1px solid #d9dfeb;
      border-radius: 0.75rem;
      background: white;
    }
    .card h2 { margin-block: 0 0.5rem; font-size: 1.2rem; }
    .card p { margin-block: 0; color: #48546a; }
    a { color: #174ea6; }
    a:hover { text-decoration-thickness: 2px; }
    a:focus-visible { outline: 3px solid #2563eb; outline-offset: 3px; }
    input[type="search"] {
      width: 100%;
      max-width: 24rem;
      padding: 0.7rem;
      border: 1px solid #7f8ba1;
      border-radius: 0.4rem;
      font: inherit;
    }
    @media (max-width: 35rem) {
      #page { width: min(100% - 1rem, 64rem); padding-block: 1rem; }
    }
  </style>
</head>
<body>
  <main id="page">
    <h1>CSS selector examples</h1>
    <p class="intro">Each card is an article. Resize the browser to see the grid adapt.</p>
    <label for="filter">Search topics</label><br>
    <input id="filter" type="search" placeholder="Try “layout”">
    <section class="card-list" aria-label="Tutorial topics">
      <article class="card">
        <h2><a href="#selectors">Selectors</a></h2>
        <p>Choose elements by type, class, attribute, state, or position.</p>
      </article>
      <article class="card">
        <h2><a href="#layout">Layout</a></h2>
        <p>Arrange content with a layout that responds to available width.</p>
      </article>
    </section>
  </main>
</body>
</html>

The .card class is reusable, #page targets the page container, and input[type="search"] matches the search control. The link rules apply to all links, with a separate hover and keyboard focus-visible treatment. Grid changes its column count as space permits, while the media query tightens page padding on narrow viewports.

6. CSS versioning and browser support

CSS is modular and continues to evolve. “CSS3” remains a useful tutorial and search phrase, but current CSS should not be described as one completed CSS3 release. The W3C specifications index and CSS snapshots provide specification context. Snapshot inclusion reflects specification maturity criteria; it does not by itself promise implementation in a particular browser. For browser support, check the specific feature’s compatibility information and test the browsers and versions your project supports.

  • Separate a feature’s specification status from its browser adoption.
  • Check support for selectors and properties individually, especially newer features.
  • When a feature is optional, consider a fallback that still gives users a usable layout.
  • Test at narrow and wide viewports, with keyboard navigation, and with the actual content lengths your page receives.

Primary references: W3C CSS overview, W3C CSS specifications index, CSS Snapshot 2025, Selectors Level 3, and the MDN selector guide.

7. Troubleshooting CSS selector problems

Symptom Likely cause What to check or change
A rule has no visible effect The selector matches no element, the stylesheet did not load, or another declaration wins Inspect the element and matched rules in browser developer tools; check the stylesheet URL and selector spelling
A class selector does not match The HTML class differs, including a typo or case difference Compare the selector with the element’s actual class list; use a dot in CSS, such as .notice
An ID selector does not match The ID value differs or the selector is written as a class Compare the exact ID in the HTML with #id-value; remember # targets IDs and . targets classes
An attribute rule misses a control The attribute is absent or its value differs from the selector Inspect the rendered attribute; [type="email"] requires that value
A child selector misses nested content > matches direct children only Use a descendant space if any nested descendant is intended, or adjust the markup
A hover style works but keyboard users cannot see focus Only the hover state was styled Add a visible :focus or :focus-visible treatment and verify keyboard navigation
A declaration is crossed out in developer tools A competing declaration wins in the cascade Inspect the winning rule, specificity, source order, and cascade layers; simplify the competing rules where possible
A newer selector does not work in one browser That browser may not support the feature Check current compatibility for the exact selector and provide a fallback if needed
A layout overflows on a small screen Fixed widths or minimum content sizes exceed the available space Use flexible sizing, allow columns to wrap, and inspect long words or unbreakable content

8. Performance, reliability, and cost

CSS has no per-request service cost when authored and served as part of your site, but it does affect maintainability and rendering work. Keep selectors understandable, avoid unnecessary duplication, and remove obsolete rules as the project evolves. For ordinary page styling, prefer simple selectors that make intended matches clear rather than relying on brittle deep structure.

CSS changes can regress appearance without causing a code error. Check representative pages and viewport sizes after changes. If you use CSS features with uneven support, verify them in your target browsers and decide on a fallback. A screenshot can help review visual changes: capture the same page before and after, at the same viewport, and compare the output while remembering that dynamic content can change between captures.

9. Or skip the browser setup

If you need a screenshot of a page to review CSS output, you can use a browser automation setup or make one API request with ScreenshotNeo. Its screenshot endpoint returns an image or PDF from a URL, and the same parameter names used by other screenshot APIs also work. See the ScreenshotNeo API documentation for options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.

Sign up for 1,000 free screenshots a month with no card.

10. FAQ

Is CSS the same as HTML?

No. HTML describes document structure and content; CSS describes how that content is presented.

Should I use a class or an ID for styling?

Use a class for styles that may apply to multiple elements. Use an ID when you need to target a particular element by its ID, and avoid making reusable styling depend on IDs.

Does a W3C specification mean every browser supports a feature?

No. Specification status and browser implementation are separate. Check support for the exact feature and the browsers relevant to your project.

What is the fastest way to see which selector matched?

Use the browser’s developer tools to inspect the element and its matched CSS rules. This also reveals declarations that lose in the cascade.