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 : 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
Complete BEM Example
BEM CSS
< 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)
/* Block */
.product-card {
border : 1 px solid #ddd ;
border-radius : 8 px ;
padding : 16 px ;
}
/* Block modifier */
.product-card--featured {
border-color : gold ;
box-shadow : 0 4 px 12 px rgba ( 0 , 0 , 0 , 0.1 );
}
/* Elements */
.product-card__image {
width : 100 % ;
height : auto ;
}
.product-card__title {
font-size : 1.25 rem ;
font-weight : 600 ;
}
.product-card__price {
color : #333 ;
font-size : 1.5 rem ;
}
/* Element modifier */
.product-card__price--sale {
color : #e74c3c ;
}
.product-card__btn {
padding : 8 px 16 px ;
border : none ;
border-radius : 4 px ;
}
.product-card__btn--primary {
background-color : #3498db ;
color : white ;
}
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
JavaScript
CSS
HTML Examples
// 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" }
/* Style based on data attribute */
[ data-cart-count ] {
position : relative ;
}
/* Show cart count badge */
[ data-cart-count ] :not ([ data-cart-count = "0" ]) ::after {
content : attr ( data-cart-count );
position : absolute ;
top : -8 px ;
right : -8 px ;
background-color : #e74c3c ;
color : white ;
border-radius : 50 % ;
padding : 2 px 6 px ;
font-size : 0.75 rem ;
}
/* Different styles based on value */
[ data-status = "active" ] {
color : green ;
}
[ data-status = "inactive" ] {
color : gray ;
}
<!-- Product card with data attributes -->
< article
class = "product-card"
data-product-id = "12345"
data-category = "electronics"
data-price = "1299"
data-in-stock = "true"
>
< h3 > Gaming Laptop </ h3 >
< button
class = "add-to-cart"
data-action = "add-to-cart"
data-product-id = "12345"
>
Add to Cart
</ button >
</ article >
<!-- Filtering with data attributes -->
< div class = "filters" >
< button data-filter = "all" > All </ button >
< button data-filter = "electronics" > Electronics </ button >
< button data-filter = "clothing" > Clothing </ button >
</ div >
<!-- State management -->
< div
class = "accordion"
data-state = "collapsed"
data-animation = "slide"
>
< button data-toggle = "accordion" > Toggle </ button >
< div class = "accordion__content" > Content </ div >
</ div >
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
href - Link Destination
<!-- 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.
<!-- 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:
CSS Selectors
JavaScript Selectors
/* 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 { }
// By ID (fastest)
document . getElementById ( 'main-header' );
// By class
document . getElementsByClassName ( 'product-card' );
// By tag name
document . getElementsByTagName ( 'article' );
// Query selector (CSS selector)
document . querySelector ( '.header__nav' );
document . querySelector ( '#main-header' );
document . querySelector ( '[data-product-id="123"]' );
// Query selector all
document . querySelectorAll ( '.product-card' );
document . querySelectorAll ( '.header__nav-link' );
// By name attribute
document . getElementsByName ( 'email' );
// Modern approaches
const header = document . querySelector ( '#main-header' );
const links = header . querySelectorAll ( '.nav-link' );
const activeLink = header . querySelector ( '.nav-link--active' );
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)