HTML <ul>, <ol>, <li> reference Jump to this section

Common attributes Jump to this section

Basic list structures Jump to this section

HTML provides two main list types: unordered lists (<ul>) for items where order doesn't matter, and ordered lists (<ol>) for sequential or ranked items. Both contain list items (<li>).

  • First item
  • Second item
  • Third item
<ul>
    <li>First item</li>
    <li>Second item</li>
    <li>Third item</li>
</ul>
  1. First step
  2. Second step
  3. Third step
<ol>
    <li>First step</li>
    <li>Second step</li>
    <li>Third step</li>
</ol>

Ordered list attributes Jump to this section

type Jump to this section

Specifies the numbering style for an ordered list.

Values: 1 (decimal numbers, default), A (uppercase letters), a (lowercase letters), I (uppercase Roman numerals), i (lowercase Roman numerals)

Use when you need alternative numbering styles for different hierarchical levels or stylistic preferences.

  1. First item
  2. Second item
  3. Third item
<ol type="A">
    <li>First item</li>
    <li>Second item</li>
    <li>Third item</li>
</ol>
<!-- Other options -->
<ol type="1"> <!-- 1, 2, 3 (default) -->
<ol type="a"> <!-- a, b, c -->
<ol type="I"> <!-- I, II, III -->
<ol type="i"> <!-- i, ii, iii -->

start Jump to this section

Specifies the starting value for an ordered list. Must be an integer, even when using letter or Roman numeral types.

Use when continuing a list after interrupting content, or starting from a specific number in rankings or steps.

  1. Fifth item
  2. Sixth item
  3. Seventh item
<ol start="5">
    <li>Fifth item</li>
    <li>Sixth item</li>
    <li>Seventh item</li>
</ol>
<!-- Works with letter types too -->
<ol type="A" start="3">
    <li>C. Third item</li>
    <li>D. Fourth item</li>
</ol>

reversed Jump to this section

Boolean attribute that reverses the numbering order. The list counts down instead of up.

Use for countdowns, reverse rankings (worst to best), or descending priority lists.

  1. Third
  2. Second
  3. First
<ol reversed>
    <li>Third</li>
    <li>Second</li>
    <li>First</li>
</ol>
<!-- Displays as: 3. Third, 2. Second, 1. First -->

List item attributes Jump to this section

value Jump to this section

Sets a specific number for an ordered list item. Subsequent items continue numbering from this value. Only works in <ol> lists.

Use when you need to skip numbers, restart numbering mid-list, or set specific values for individual items.

  1. First item
  2. Tenth item
  3. Eleventh item
  4. Twelfth item
<ol>
    <li>First item</li>
    <li value="10">Tenth item</li>
    <li>Eleventh item</li>
    <li>Twelfth item</li>
</ol>
<!-- Displays as: 1, 10, 11, 12 -->

Nested lists Jump to this section

Lists can be nested inside list items to create hierarchical structures. The nested list must be placed inside an <li> element.

Use for table of contents, organizational hierarchies, category/subcategory structures, or multi-level navigation.

  • Fruits
    • Apples
    • Oranges
    • Bananas
  • Vegetables
    • Carrots
    • Broccoli
    • Spinach
<ul>
    <li>Fruits
        <ul>
            <li>Apples</li>
            <li>Oranges</li>
            <li>Bananas</li>
        </ul>
    </li>
    <li>Vegetables
        <ul>
            <li>Carrots</li>
            <li>Broccoli</li>
            <li>Spinach</li>
        </ul>
    </li>
</ul>

You can also mix list types when nesting:

<ol>
    <li>Main topic
        <ul>
            <li>Bullet point about topic</li>
            <li>Another bullet point</li>
        </ul>
    </li>
    <li>Second topic
        <ul>
            <li>Detail about second topic</li>
        </ul>
    </li>
</ol>

Accessibility attributes Jump to this section

role Jump to this section

Specifies the semantic role of the element. Lists have implicit roles (list and listitem), but these can be overridden if needed.

Note: Some CSS resets remove list semantics. Explicitly adding role="list" ensures accessibility is maintained.

<ul role="list">
    <li role="listitem">Item 1</li>
    <li role="listitem">Item 2</li>
</ul>
<!-- Use when list styling is removed -->
<ul style="list-style: none;" role="list">
    <li>Item without bullet</li>
</ul>

aria-label Jump to this section

Provides an accessible label for the list when a visible heading isn't present or when you need to clarify the list's purpose.

<ul aria-label="Navigation menu">
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
</ul>
<ul aria-label="Social media links">
    <li><a href="#">Twitter</a></li>
    <li><a href="#">Facebook</a></li>
</ul>

aria-labelledby Jump to this section

References a heading or label element by its id to provide context for the list. Preferred over aria-label when a visible heading exists.

<h2 id="features-heading">Product Features</h2>
<ul aria-labelledby="features-heading">
    <li>Feature 1</li>
    <li>Feature 2</li>
    <li>Feature 3</li>
</ul>

aria-describedby Jump to this section

References additional descriptive text to provide context or instructions for the list.

<p id="task-instructions">Click items to mark as complete</p>
<ul aria-describedby="task-instructions">
    <li>Task 1</li>
    <li>Task 2</li>
</ul>

data-* attributes Jump to this section

Custom attributes for storing application-specific data on list elements. Accessible via JavaScript's dataset property.

<ul data-list-type="tasks" data-filter="active">
    <li data-task-id="1" data-priority="high" data-status="pending">
        Complete project proposal
    </li>
    <li data-task-id="2" data-priority="low" data-status="completed">
        Review meeting notes
    </li>
</ul>
<script>
  const list = document.querySelector('ul');
  console.log(list.dataset.listType); // "tasks"
  console.log(list.dataset.filter);   // "active"
  const firstItem = list.querySelector('li');
  console.log(firstItem.dataset.taskId);   // "1"
  console.log(firstItem.dataset.priority); // "high"
  console.log(firstItem.dataset.status);   // "pending"
</script>

id Jump to this section

Unique identifier for the list element. Essential for linking with labels, JavaScript selection, and CSS targeting.

<h2>Shopping List</h2>
<ul id="shopping-list">
    <li>Milk</li>
    <li>Bread</li>
    <li>Eggs</li>
</ul>
<script>
  const list = document.getElementById('shopping-list');
  console.log(list.children.length); // 3
</script>

class Jump to this section

Assigns CSS class names for styling or JavaScript selection. Multiple classes can be applied.

<ul class="feature-list highlighted-list">
    <li class="premium-feature">Premium Feature</li>
    <li class="basic-feature">Basic Feature</li>
</ul>
<style>
  .feature-list { padding: 20px; }
  .premium-feature { color: gold; }
</style>

title Jump to this section

Provides tooltip text on hover. Not accessible to keyboard-only users or touch devices, so avoid for critical information.

<ul title="List of available options">
    <li>Option 1</li>
    <li>Option 2</li>
</ul>

Styling basics Jump to this section

List elements offer extensive styling options. The list-style property controls marker appearance, while flexbox and grid enable modern layouts beyond traditional vertical lists.

List style types Jump to this section

Unordered list markers Jump to this section

  • Disc (default)
  • Circle
  • Square
  • None
ul { list-style-type: disc; }   /* Default */
ul { list-style-type: circle; }
ul { list-style-type: square; }
ul { list-style-type: none; }   /* No marker */

Ordered list markers Jump to this section

  1. Decimal (1, 2, 3)
  1. Upper Alpha (A, B, C)
  1. Lower Alpha (a, b, c)
  1. Upper Roman (I, II, III)
  1. Lower Roman (i, ii, iii)
ol { list-style-type: decimal; }      /* 1, 2, 3 */
ol { list-style-type: upper-alpha; }  /* A, B, C */
ol { list-style-type: lower-alpha; }  /* a, b, c */
ol { list-style-type: upper-roman; }  /* I, II, III */
ol { list-style-type: lower-roman; }  /* i, ii, iii */

Custom markers Jump to this section

  • Checkmark item
  • Another item
  • Arrow item
  • Another item
  • Star item
  • Another item
ul { list-style-type: '✓ '; }
ul { list-style-type: '→ '; }
ul { list-style-type: '★ '; }
ul { list-style-type: '🎯 '; }

List style position Jump to this section

Controls whether markers appear inside or outside the content flow.

  • Outside - marker sits outside the content area (default)
  • Inside - marker is part of the content flow
ul { list-style-position: outside; } /* Default */
ul { list-style-position: inside; }

Reset default styling Jump to this section

  • No bullets
  • No padding
  • No margin
.list-reset {
    list-style: none;
    padding: 0;
    margin: 0;
}

Horizontal lists Jump to this section

Basic horizontal list Jump to this section

  • Item 1
  • Item 2
  • Item 3
.horizontal-list {
    list-style: none;
    padding: 0;
    display: flex;
    gap: 20px;
}

With separators Jump to this section

  • Item 1
  • Item 2
  • Item 3
.separated-list {
    list-style: none;
    padding: 0;
    display: flex;
}
.separated-list li {
    padding: 0 15px;
    border-right: 1px solid #d1d5db;
}
.separated-list li:last-child {
    border-right: none;
}

Grid layout Jump to this section

  • Item 1
  • Item 2
  • Item 3
  • Item 4
.grid-list {
    list-style: none;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}

Styled list examples Jump to this section

Modern checklist Jump to this section

  • Completed task
  • Pending task
  • Another pending task
.checklist {
    list-style: none;
    padding: 0;
}
.checklist li {
    padding: 12px;
    margin-bottom: 8px;
    border-left: 3px solid #9ca3af;
    border-radius: 4px;
    background: #f3f4f6;
}
.checklist li.completed {
    background: #f0fdf4;
    border-left-color: #16a34a;
}

Numbered steps Jump to this section

  1. 1 First step description
  2. 2 Second step description
  3. 3 Third step description
.steps {
    list-style: none;
    padding: 0;
    counter-reset: step;
}
.steps li {
    padding: 15px 15px 15px 50px;
    margin-bottom: 10px;
    background: #eff6ff;
    border-radius: 6px;
    position: relative;
    counter-increment: step;
}
.steps li::before {
    content: counter(step);
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 28px;
    height: 28px;
    background: #3b82f6;
    color: white;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
}

Card-style list Jump to this section

  • Card Item 1 Description text goes here
  • Card Item 2 Description text goes here
  • Card Item 3 Description text goes here
.card-list {
    list-style: none;
    padding: 0;
}
.card-list li {
    padding: 16px;
    margin-bottom: 12px;
    background: white;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
    transition: all 0.2s;
}
.card-list li:hover {
    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    transform: translateY(-2px);
}

Tag/pill list Jump to this section

  • JavaScript
  • React
  • CSS
  • HTML
.tag-list {
    list-style: none;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.tag-list li {
    padding: 6px 14px;
    background: #dbeafe;
    color: #1e40af;
    border-radius: 20px;
    font-size: 14px;
    font-weight: 500;
}

Icon list Jump to this section

  • Feature one included
  • Feature two included
  • Feature three included
.icon-list {
    list-style: none;
    padding: 0;
}
.icon-list li {
    padding: 10px 0;
    display: flex;
    align-items: center;
    gap: 12px;
}
.icon-list li::before {
    content: '✓';
    width: 24px;
    height: 24px;
    background: #3b82f6;
    color: white;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

Divided list Jump to this section

  • First item
  • Second item
  • Third item
  • Fourth item
.divided-list {
    list-style: none;
    padding: 0;
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    overflow: hidden;
}
.divided-list li {
    padding: 12px 16px;
    border-bottom: 1px solid #e5e7eb;
}
.divided-list li:last-child {
    border-bottom: none;
}

Custom counters Jump to this section

  1. Step 1: First instruction
  2. Step 2: Second instruction
  3. Step 3: Third instruction
.custom-counter {
    list-style: none;
    padding: 0;
    counter-reset: custom;
}
.custom-counter li {
    counter-increment: custom;
    padding-left: 60px;
    position: relative;
}
.custom-counter li::before {
    content: "Step " counter(custom) ":";
    position: absolute;
    left: 0;
    font-weight: bold;
    color: #3b82f6;
}

Spacing utilities Jump to this section

/* Increase space between items */
.list-spaced li {
    margin-bottom: 16px;
}
/* Compact list */
.list-compact li {
    line-height: 1.4;
}
/* Add padding to items */
.list-padded li {
    padding: 8px 0;
}
>

JavaScript patterns Jump to this section

List elements are commonly manipulated with JavaScript for dynamic content, filtering, sorting, and interactive features.

Adding list items Jump to this section

Dynamically create and append new items to a list.

  • Existing item
const list = document.getElementById('my-list');
// Create new list item
const li = document.createElement('li');
li.textContent = 'New item';
// Add to end of list
list.appendChild(li);
// Add to beginning
list.insertBefore(li, list.firstChild);
// Add at specific position (e.g., 3rd position)
list.insertBefore(li, list.children[2]);
// Add with HTML content
li.innerHTML = '<strong>Bold</strong> item';

Removing list items Jump to this section

Remove items individually or clear the entire list.

  • Item 1
  • Item 2
  • Item 3
const list = document.getElementById('my-list');
// Remove specific item
const item = list.children[0];
item.remove();
// Remove all items
list.innerHTML = '';
// Remove with event delegation
list.addEventListener('click', (e) => {
    if (e.target.classList.contains('remove-btn')) {
        e.target.closest('li').remove();
    }
});

Toggle completed state Jump to this section

Toggle classes to mark items as complete or incomplete.

  • Click to toggle completion
  • Another task to complete
  • Third task
const list = document.getElementById('task-list');
list.addEventListener('click', (e) => {
    if (e.target.tagName === 'LI') {
        e.target.classList.toggle('completed');
    }
});
// CSS for completed state
// .completed {
//     text-decoration: line-through;
//     opacity: 0.6;
//     background: #dcfce7;
// }

Filter list items Jump to this section

Show or hide items based on search input.

  • Apple
  • Banana
  • Cherry
  • Date
  • Elderberry
  • Fig
const input = document.getElementById('filter-input');
const list = document.getElementById('filter-list');
input.addEventListener('input', (e) => {
    const filter = e.target.value.toLowerCase();
    const items = list.getElementsByTagName('li');
    Array.from(items).forEach(item => {
        const text = item.textContent.toLowerCase();
        if (text.includes(filter)) {
            item.style.display = '';
        } else {
            item.style.display = 'none';
        }
    });
});

Sort list items Jump to this section

Sort items alphabetically or by custom criteria.

  • Zebra
  • Apple
  • Mango
  • Banana
  • Cherry
function sortList(listId, direction = 'asc') {
    const list = document.getElementById(listId);
    const items = Array.from(list.children);
    items.sort((a, b) => {
        const textA = a.textContent.trim();
        const textB = b.textContent.trim();
        if (direction === 'asc') {
            return textA.localeCompare(textB);
        } else {
            return textB.localeCompare(textA);
        }
    });
    // Re-append sorted items
    items.forEach(item => list.appendChild(item));
}
// Sort by custom criteria
function sortByDataAttribute(listId, attribute) {
    const list = document.getElementById(listId);
    const items = Array.from(list.children);
    items.sort((a, b) => {
        return a.dataset[attribute] - b.dataset[attribute];
    });
    items.forEach(item => list.appendChild(item));
}

Drag and drop reordering Jump to this section

Enable users to reorder items by dragging.

  • ⋮⋮ Drag item 1
  • ⋮⋮ Drag item 2
  • ⋮⋮ Drag item 3
  • ⋮⋮ Drag item 4
const list = document.getElementById('drag-list');
let draggedItem = null;
list.addEventListener('dragstart', (e) => {
    draggedItem = e.target;
    e.target.style.opacity = '0.5';
});
list.addEventListener('dragend', (e) => {
    e.target.style.opacity = '';
});
list.addEventListener('dragover', (e) => {
    e.preventDefault();
    const afterElement = getDragAfterElement(list, e.clientY);
    if (afterElement == null) {
        list.appendChild(draggedItem);
    } else {
        list.insertBefore(draggedItem, afterElement);
    }
});
function getDragAfterElement(container, y) {
    const draggableElements = [
        ...container.querySelectorAll('li:not(.dragging)')
    ];
    return draggableElements.reduce((closest, child) => {
        const box = child.getBoundingClientRect();
        const offset = y - box.top - box.height / 2;
        if (offset < 0 && offset > closest.offset) {
            return { offset: offset, element: child };
        } else {
            return closest;
        }
    }, { offset: Number.NEGATIVE_INFINITY }).element;
}

Count list items Jump to this section

Track and display the number of items in a list.

  • Item 1
  • Item 2
  • Item 3
Total items: 3
const list = document.getElementById('count-list');
const display = document.getElementById('count-display');
function updateCount() {
    const count = list.children.length;
    display.textContent = `Total items: ${count}`;
}
// Update whenever list changes
const observer = new MutationObserver(updateCount);
observer.observe(list, { childList: true });
// Or manually trigger updates
updateCount(); // Initial count

Generate list from array Jump to this section

Create list items dynamically from data.

  • Click button to generate list...
const data = ['Apple', 'Banana', 'Cherry', 'Date'];
const list = document.getElementById('my-list');
// Method 1: createElement
list.innerHTML = ''; // Clear existing
data.forEach(item => {
    const li = document.createElement('li');
    li.textContent = item;
    list.appendChild(li);
});
// Method 2: Template literals
list.innerHTML = data
    .map(item => `<li>${item}</li>`)
    .join('');
// With data attributes
const items = [
    { id: 1, name: 'Item 1', priority: 'high' },
    { id: 2, name: 'Item 2', priority: 'low' }
];
list.innerHTML = items
    .map(item => `
        <li data-id="${item.id}" data-priority="${item.priority}">
            ${item.name}
        </li>
    `)
    .join('');

Select/highlight items Jump to this section

Allow users to select items by clicking.

  • Click to select item 1
  • Click to select item 2
  • Click to select item 3
const list = document.getElementById('select-list');
list.addEventListener('click', (e) => {
    if (e.target.tagName === 'LI') {
        // Remove selected class from all
        list.querySelectorAll('li').forEach(item => {
            item.classList.remove('selected');
        });
        // Add to clicked item
        e.target.classList.add('selected');
    }
});
// Get selected item
function getSelected() {
    return list.querySelector('li.selected');
}
// CSS
// .selected {
//     background: #dbeafe;
//     font-weight: bold;
// }

Multi-select with checkboxes Jump to this section

Enable multiple item selection with checkboxes.

  • Item 1
  • Item 2
  • Item 3
  • Item 4
const list = document.getElementById('checkbox-list');
// Get all checked items
function getSelected() {
    const checkboxes = list.querySelectorAll('input:checked');
    return Array.from(checkboxes).map(cb => {
        return cb.closest('li').textContent.trim();
    });
}
// Select all
function selectAll() {
    list.querySelectorAll('input[type="checkbox"]')
        .forEach(cb => cb.checked = true);
}
// Deselect all
function deselectAll() {
    list.querySelectorAll('input[type="checkbox"]')
        .forEach(cb => cb.checked = false);
}
// Toggle all
function toggleAll() {
    list.querySelectorAll('input[type="checkbox"]')
        .forEach(cb => cb.checked = !cb.checked);
}

Pagination Jump to this section

Display large lists across multiple pages.

    Page 1 of 10
    const data = Array.from({length: 50}, (_, i) => `Item ${i + 1}`);
    const itemsPerPage = 5;
    let currentPage = 1;
    const list = document.getElementById('page-list');
    const prevBtn = document.getElementById('prev-btn');
    const nextBtn = document.getElementById('next-btn');
    const pageInfo = document.getElementById('page-info');
    function renderPage() {
        const start = (currentPage - 1) * itemsPerPage;
        const end = start + itemsPerPage;
        const pageData = data.slice(start, end);
        list.innerHTML = pageData
            .map(item => `<li>${item}</li>`)
            .join('');
        const totalPages = Math.ceil(data.length / itemsPerPage);
        pageInfo.textContent = `Page ${currentPage} of ${totalPages}`;
        // Update button states
        prevBtn.disabled = currentPage === 1;
        nextBtn.disabled = currentPage === totalPages;
    }
    prevBtn.onclick = () => {
        if (currentPage > 1) {
            currentPage--;
            renderPage();
        }
    };
    nextBtn.onclick = () => {
        const totalPages = Math.ceil(data.length / itemsPerPage);
        if (currentPage < totalPages) {
            currentPage++;
            renderPage();
        }
    };
    // Initial render
    renderPage();

    Iterate over items Jump to this section

    Loop through list items to read or modify them.

    const list = document.getElementById('my-list');
    // Using forEach
    Array.from(list.children).forEach((item, index) => {
        console.log(`Item ${index}: ${item.textContent}`);
    });
    // Using for...of
    for (const item of list.children) {
        item.style.color = 'blue';
    }
    // Using querySelectorAll
    list.querySelectorAll('li').forEach(item => {
        item.addEventListener('click', () => {
            console.log('Clicked:', item.textContent);
        });
    });
    

    Find specific items Jump to this section

    Search for items matching specific criteria.

    const list = document.getElementById('my-list');
    // Find by text content
    const item = Array.from(list.children)
        .find(li => li.textContent === 'Search term');
    // Find by data attribute
    const itemByAttr = list.querySelector('[data-id="123"]');
    // Find all matching a condition
    const completedItems = Array.from(list.children)
        .filter(li => li.classList.contains('completed'));
    // Find by custom criteria
    const highPriorityItems = Array.from(list.children)
        .filter(li => li.dataset.priority === 'high');