Skip to main content
HTML attributes provide additional information about elements, configuring their behavior and enabling styling and JavaScript interactions.

Understanding Attributes

Attributes are added to opening tags and follow the format name="value":
<element attribute="value">Content</element>
Multiple attributes are separated by spaces:
<img src="logo.png" alt="Company Logo" width="200" height="100" loading="lazy" />

Essential Attributes

id - Unique Identifier

The id attribute creates a unique identifier for an element:
<header class="header" id="main-header">
  <!-- Header content -->
</header>
Characteristics:
  • Must be unique in the entire document
  • Used for:
    • JavaScript selection: document.getElementById('main-header')
    • CSS styling: #main-header { }
    • Anchor links: <a href="#main-header">Go to header</a>
    • Form label associations: <label for="email-input">
Naming rules:
  • Must start with a letter (a-z or A-Z)
  • Can contain letters, digits, hyphens, underscores
  • Case-sensitive
  • No spaces
<!-- Good IDs -->
<div id="main-content"></div>
<form id="login-form"></form>
<button id="submit-btn"></button>

<!-- JavaScript usage -->
<script>
const header = document.getElementById('main-header');
const form = document.getElementById('login-form');
</script>

<!-- CSS usage -->
<style>
#main-header {
  background-color: #fff;
  position: sticky;
  top: 0;
}
</style>

<!-- Anchor link usage -->
<a href="#products-section">View Products</a>
<!-- Scrolls to: -->
<section id="products-section">
  <!-- Products -->
</section>
Never duplicate IDs! Each ID must be unique in the document. Use classes for styling multiple elements.
<!-- WRONG: Duplicate IDs -->
<div id="product">Product 1</div>
<div id="product">Product 2</div>

<!-- CORRECT: Use classes -->
<div class="product">Product 1</div>
<div class="product">Product 2</div>

class - Reusable Styles

The class attribute groups elements for styling and JavaScript selection:
<div class="header__container">
  <nav class="header__nav">
    <a href="#" class="header__nav-link">Home</a>
    <a href="#" class="header__nav-link header__nav-link--active">Products</a>
  </nav>
</div>
Characteristics:
  • Reusable - multiple elements can have the same class
  • Multiple classes - one element can have multiple classes
  • Used for:
    • CSS styling: .header__nav { }
    • JavaScript selection: document.querySelectorAll('.product-card')
Multiple classes:
<!-- Element with 3 classes -->
<button class="btn btn--primary btn--large">
  Click Me
</button>

BEM Methodology

BEM (Block Element Modifier) is a naming convention for CSS classes that makes code more maintainable and understandable.

BEM Structure

block__element--modifier
  • Block: Independent component (header, button, card)
  • Element: Part of a block, uses __ (header__logo, card__title)
  • Modifier: Variation or state, uses -- (button--primary, card--featured)

Block - The Component

A standalone entity that makes sense on its own:
<header class="header">
  <!-- The 'header' block -->
</header>

<article class="product-card">
  <!-- The 'product-card' block -->
</article>
Block naming:
  • Describes purpose: header, menu, product-card
  • Doesn’t describe state: not red-text or big-button

Element - Parts of a Block

Parts of a block that have no meaning on their own:
<header class="header">
  <div class="header__container">
    <div class="header__logo">
      <a href="/" class="header__logo-link">
        <span class="header__logo-text">ML</span>
        <span class="header__logo-subtitle">Store</span>
      </a>
    </div>
    
    <nav class="header__nav">
      <ul class="header__nav-list">
        <li class="header__nav-item">
          <a href="#" class="header__nav-link">Home</a>
        </li>
      </ul>
    </nav>
  </div>
</header>
Element naming:
  • Format: block__element
  • Examples: header__logo, header__nav, header__nav-link
  • Can chain words with hyphens: header__logo-link, product-card__buy-button

Modifier - Variations and States

Flags that change appearance or behavior:
<!-- Cart link with modifier for cart count -->
<a href="#" class="header__nav-link header__nav-link--cart" data-cart-count="3">
  <span>Carrito</span>
</a>

<!-- Button variations -->
<button class="btn btn--primary">Primary Button</button>
<button class="btn btn--secondary">Secondary Button</button>
<button class="btn btn--disabled" disabled>Disabled</button>

<!-- Card states -->
<article class="product-card product-card--featured">
  <!-- Featured product -->
</article>
Modifier naming:
  • Format: block--modifier or block__element--modifier
  • Examples: button--primary, header__nav-link--active
  • Boolean modifiers: card--featured, menu--open
  • Key-value modifiers: button--size-large, theme--color-blue
<article class="product-card product-card--featured">
  <figure class="product-card__figure">
    <img 
      src="laptop.jpg" 
      alt="Gaming Laptop" 
      class="product-card__image"
    />
  </figure>
  
  <div class="product-card__content">
    <span class="product-card__category">Electronics</span>
    <h3 class="product-card__title">Gaming Laptop Pro</h3>
    <p class="product-card__price product-card__price--sale">
      <span class="product-card__price-original">$1,499</span>
      <span class="product-card__price-current">$1,299</span>
    </p>
    <button class="product-card__btn product-card__btn--primary">
      Add to Cart
    </button>
  </div>
</article>
Breakdown:
  • product-card - Block (the component)
  • product-card--featured - Block modifier (variant)
  • product-card__figure - Element (part of card)
  • product-card__image - Element (part of card)
  • product-card__price--sale - Element modifier (sale state)

BEM Benefits

Clarity

Class names describe structure and purpose clearly

Modularity

Blocks are independent and reusable

Specificity

Flat structure avoids CSS specificity issues

Scalability

Easy to maintain large codebases

Data Attributes

Custom attributes for storing data in HTML elements:
<a 
  href="#" 
  class="header__nav-link header__nav-link--cart" 
  data-cart-count="0"
>
  <span>Carrito</span>
</a>
Format: Always starts with data-

Accessing Data Attributes

// Get element
const cartLink = document.querySelector('[data-cart-count]');

// Read data attribute
const count = cartLink.dataset.cartCount; // "0"

// Update data attribute
cartLink.dataset.cartCount = "5";

// Multiple data attributes
const product = document.querySelector('.product-card');
product.dataset.productId = "123";
product.dataset.category = "electronics";
product.dataset.inStock = "true";

console.log(product.dataset);
// { productId: "123", category: "electronics", inStock: "true" }

Common Uses for Data Attributes

  • Product information: IDs, prices, categories
  • State management: open/closed, active/inactive
  • JavaScript hooks: Identifying elements for event handlers
  • Configuration: Settings for plugins or components
  • Analytics: Tracking user interactions

Other Important Attributes

<!-- External link -->
<a href="https://www.example.com">Visit Example</a>

<!-- Internal page -->
<a href="/products">Products</a>

<!-- Anchor link (same page) -->
<a href="#products-section">Jump to Products</a>

<!-- Email -->
<a href="mailto:support@mlstore.com">Email Us</a>

<!-- Phone -->
<a href="tel:+15551234567">Call Us</a>

src - Resource Source

<!-- Image -->
<img src="/images/logo.png" alt="Logo" />

<!-- Script -->
<script src="/js/main.js"></script>

<!-- Iframe -->
<iframe src="https://www.youtube.com/embed/VIDEO_ID"></iframe>

alt - Alternative Text

<!-- Descriptive alt text -->
<img src="laptop.jpg" alt="Silver gaming laptop with RGB keyboard" />

<!-- Decorative image (empty alt) -->
<img src="decoration.png" alt="" />

<!-- Logo -->
<img src="logo.png" alt="ML Store - Home" />
Always include the alt attribute on images, even if empty. It’s crucial for accessibility and SEO.

type - Input/Button Type

<!-- Input types -->
<input type="text" placeholder="Name" />
<input type="email" placeholder="Email" />
<input type="password" placeholder="Password" />
<input type="search" placeholder="Search..." />
<input type="number" min="0" max="100" />
<input type="checkbox" />
<input type="radio" name="option" />
<input type="file" />

<!-- Button types -->
<button type="submit">Submit Form</button>
<button type="button">Just a Button</button>
<button type="reset">Reset Form</button>

ARIA Attributes - Accessibility

<!-- Label for screen readers -->
<button class="header__search-button" aria-label="Buscar">
  <svg><!-- Search icon --></svg>
</button>

<!-- Live regions -->
<div aria-live="polite" id="status-message">
  <!-- Screen readers announce changes -->
</div>

<!-- Navigation landmarks -->
<nav aria-label="Main navigation">
  <!-- Links -->
</nav>

<!-- Hidden from screen readers -->
<span aria-hidden="true">🎉</span>

Selectors for CSS and JavaScript

Different ways to select elements:
/* Element selector */
header { }

/* ID selector */
#main-header { }

/* Class selector */
.header { }
.header__nav { }

/* Descendant selector */
.header .nav-link { }

/* Direct child */
.header > .nav { }

/* Multiple classes */
.btn.btn--primary { }

/* Attribute selectors */
[type="text"] { }
[data-category] { }
[href^="https"] { } /* starts with */
[href$=".pdf"] { } /* ends with */
[class*="btn"] { } /* contains */

/* Pseudo-classes */
.nav-link:hover { }
.nav-link:focus { }
.item:first-child { }
.item:nth-child(2) { }

/* Pseudo-elements */
.nav-link::before { }
.nav-link::after { }

Best Practices

Do

  • Use IDs sparingly and only when unique
  • Use classes for styling multiple elements
  • Follow BEM naming for consistency
  • Add alt text to all images
  • Use data attributes for custom data
  • Choose semantic attribute names

Don't

  • Don’t duplicate IDs in a document
  • Don’t use IDs for styling (use classes)
  • Don’t use inline styles (use classes)
  • Don’t forget ARIA labels on icon buttons
  • Don’t use generic class names like .text or .box
  • Don’t nest BEM elements (block__elem__elem)