Contents

    Guides

    What Are Cypress Selectors and How to Use Them

    Published on

    February 23, 2026
    What Are Cypress Selectors and How to Use Them

    If you’ve ever tried testing a web app, you know how tricky it can be to grab the exact element you want. That’s where Cypress selectors come in. They help you pinpoint buttons, inputs, links, or any part of the page so your tests run smoothly without breaking.

    However, selectors do more than just find elements. With the right ones, you can check if buttons are clickable, inputs accept text, or styles appear as expected. You can combine selectors to target complex layouts, use attributes to grab dynamic elements, and even test styles directly. This makes writing tests more precise and ensures your app behaves exactly as intended.

    In this article, I will show how to use Cypress selectors effectively for testing web apps.

    What are Cypress Selectors and Why Use Them?

    Cypress selectors are how you locate elements on a web page so your tests can interact with them. Cypress primarily uses CSS selectors, which means you can target elements using IDs, classes, attributes, or their position in the DOM. Without selectors, Cypress wouldn’t know which button to click, which input to type into, or which element’s style to check.

    For example, #login-button targets a button with that ID, while .form-input selects all elements with that class. You can also use attribute selectors like [type="submit"] to pick specific buttons or inputs. This ensures Cypress interacts with the exact element you intend, even when the page has multiple similar elements.

    Cypress selectors also let you check styles or element states. Using .error-message makes it easy to verify whether an error appears after a failed login, while [disabled] ensures buttons are correctly disabled when required. This makes tests precise and reduces failures caused by hitting the wrong element.

    Basic CSS Selectors You Need to Know

    When testing a web app in Cypress, the first thing you need is a reliable way to locate elements. CSS selectors are the foundation for this. Using the right selector ensures Cypress interacts with exactly the element you want, even if the page has multiple similar elements.

    Here are the basics you should start with:

    1. ID Selector (#id)

    Use this when an element has a unique ID on the page. This is the most precise and fastest way to select a single element because IDs should only appear once in the DOM. Ideal for buttons, forms, or any element that has a unique identifier.

    Example in Cypress:

    cy.get('#submit-btn').click(); // clicks the button with ID 'submit-btn'

    2. Class Selector (.class)

    Use this when you want to select elements sharing a common style or behavior. Classes are often used for input fields, buttons, or repeated components. If multiple elements share the same class, Cypress will target all of them, so sometimes you’ll need to combine it with other selectors.

    Example in Cypress:

    cy.get('.form-input').type('hello'); // types 'hello' into all input fields with class 'form-input'

    3. Type Selector (element)

    Use this when you want to select elements by their HTML tag, like buttons, links, or inputs. This works best when the element type is unique within the container or section you’re testing. It’s a simple way to grab elements without relying on IDs or classes.

    Example in Cypress:

    cy.get('button').contains('Login').click(); // clicks the button element containing text 'Login'

    Attribute Selectors in Cypress

    Attribute selectors let you target elements based on their HTML attributes. They are extremely useful when elements don’t have unique IDs or classes, or when you want more precise targeting. Here are the main types:

    1. Has Attribute Selector ([attr])

    Use this when you just need to check for the presence of an attribute, regardless of its value. This is helpful for verifying elements that have dynamic attributes or optional properties.

    Example in Cypress:

    cy.get('[data-active]') // selects all elements that have the 'data-active' attribute

    2. Exact Attribute Selector ([attr="value"])

    Use this when you want to select elements with an attribute set to a specific value. This ensures you target exactly the element you intend.

    Example in Cypress:

    cy.get('[data-active="true"]') // selects elements where 'data-active' is exactly 'true'

    3. Begins With Selector ([attr^="value"])

    Use this when an attribute starts with a specific value. This is helpful for dynamic IDs or attributes that follow a predictable prefix pattern.

    Example in Cypress:

    cy.get('[data-color^="r"]') // selects elements whose 'data-color' starts with 'r'

    4. Ends With Selector ([attr$="value"])

    Use this when an attribute ends with a specific value. This is useful for elements where the suffix of an attribute determines its role or state.

    Example in Cypress:

    cy.get('[data-color$="r"]') // selects elements whose 'data-color' ends with 'r'

    5. Substring Selector ([attr*="value"])

    Use this when an attribute contains a specific substring anywhere. This is flexible for dynamic attributes or partial matches.

    Example in Cypress:

    cy.get('[data-color*="e"]') // selects elements where 'data-color' contains the letter 'e'

    Combination Selectors in Cypress

    Combination selectors allow you to combine selectors or use relationships between elements. They are essential for targeting elements within complex or nested layouts.

    1. Descendant Selector (ancestor descendant)

    Use this to select elements that are nested anywhere inside a parent element. This is useful when you want to interact with elements inside a container.

    Example in Cypress:

    cy.get('.container p') // selects all p tags inside elements with class 'container'

    2. Child Selector (parent > child)

    Use this to select direct children of a parent element. This avoids accidentally selecting deeper nested elements.

    Example in Cypress:

    cy.get('.container > p') // selects only p tags directly under '.container'

    3. General Sibling Selector (element1 ~ element2)

    Use this to select all sibling elements that come after a specific element. This is helpful when you need to target elements that follow a certain node.

    Example in Cypress:

    cy.get('.box ~ p') // selects all p tags that come after '.box'

    4. Adjacent Sibling Selector (element1 + element2)

    Use this to select the element immediately following another element. This is precise for cases where only the next sibling matters.

    Example in Cypress:

    cy.get('.box + p') // selects the p tag directly after '.box'

    5. Or Selector (selector1, selector2)

    Use this to select elements that match at least one of multiple selectors. This is handy when multiple elements could fulfill the same role.

    Example in Cypress:

    cy.get('.square, #rect') // selects elements with class 'square' or ID 'rect'

    6. And Selector (selector1.selector2)

    Use this to select elements that match all specified selectors at once, such as multiple classes or a combination of type and class.

    Example in Cypress:

    cy.get('div.black') // selects div elements that also have the class 'black'

    How to Locate Elements Using CSS Selectors

    Locating elements correctly is the first step in writing reliable Cypress tests. Follow these steps to find elements efficiently:

    Step 1: Inspect the Element in the Browser

    Open your web app in the browser, right-click the element you want to test, and choose Inspect. This opens the DevTools, showing the element’s HTML, classes, IDs, and attributes.

    Example:

    // Suppose the element has <button id="submit-btn" class="btn primary"> cy.get('#submit-btn').click();

    Step 2: Decide the Most Reliable Selector

    Check if the element has a unique ID—this is usually the best option. If not, look for a class, attribute, or combination that uniquely identifies the element.

    Example using class:

    cy.get('.btn.primary').click(); // clicks the button with both 'btn' and 'primary' classes

    Step 3: Test Using Attributes for Dynamic Elements

    If IDs or classes are dynamic, use attribute selectors like data-cy, type, or name to target the element reliably.

    Example:

    cy.get('[data-cy="login-button"]').click(); // clicks the login button using a custom data attribute

    Step 4: Use Combination Selectors for Nested Elements

    For elements inside a container or deeply nested, combine selectors or use child/descendant selectors to pinpoint the element.

    Example:

    cy.get('#login-form > .btn').click(); // clicks the button directly inside the login form

    Step 5: Validate the Selector

    Before writing full test logic, check if the selector selects the correct element using Cypress commands like .should('exist') or .should('be.visible').

    Example:

    cy.get('[data-cy="submit"]').should('be.visible'); // ensures the element is visible

    Following these steps ensures your Cypress tests target the correct elements reliably, reducing flaky tests and saving time debugging.

    How to Test CSS Style Using Cypress

    After you’ve located an element with a CSS selector, you often want to verify its visual appearance, visibility, or state. Cypress allows you to check CSS properties directly, making it easy to ensure the UI behaves as expected. Follow these steps:

    Step 1: Select the Element Using a CSS Selector

    Use the selectors you already identified to target the element. This ensures you’re testing the correct element before checking its styles.

    Example:

    cy.get('#submit-btn') // selects the button with ID 'submit-btn'

    Step 2: Check Visibility

    Ensure the element is visible on the page. This is a basic but essential style check to verify that the element is rendered correctly.

    Example:

    cy.get('#submit-btn').should('be.visible'); // confirms the button is visible

    Step 3: Check Specific CSS Properties

    Use .should('have.css', property, value) to verify exact styles like color, font size, or background.

    Example:

    // Check the button’s background color cy.get('#submit-btn').should('have.css', 'background-color', 'rgb(0, 123, 255)'); // Check font size cy.get('#submit-btn').should('have.css', 'font-size', '16px');

    Step 4: Check Classes or State Changes

    Sometimes elements change style based on state (e.g., hover, active, error). Verify this by checking classes or attribute changes.

    Example:

    // Verify error class appears on invalid input cy.get('.form-input').type('wrong').blur(); cy.get('.form-input').should('have.class', 'input-error');

    Step 5: Combine Selectors for Nested or Dynamic Styles

    If the element is inside a container or dynamically generated, combine selectors to target it precisely before checking styles.

    Example:

    cy.get('#login-form > .btn').should('have.css', 'color', 'rgb(255, 255, 255)'); // checks text color of the button inside login form

    Step 6: Use Assertions for Multiple Properties

    You can check multiple CSS properties in sequence to ensure full style verification.

    Example:

    cy.get('#submit-btn') .should('have.css', 'background-color', 'rgb(0, 123, 255)') .and('have.css', 'font-size', '16px') .and('be.visible');

    Once you’ve verified styles and states using CSS selectors, it’s important to remember that visual appearance and behavior can vary across browsers and devices. A button that looks correct in one browser may render differently in another, or styles may break on smaller screens.

    To ensure your tests are truly reliable, it’s helpful to run them in real-world conditions. Tools like BrowserStack allow you to execute Cypress tests across multiple browsers, screen sizes, and operating systems, giving you confidence that your selectors and styles work consistently for all users.

    Why is My CSS Selector Not Working in Cypress?

    Sometimes, a selector that looks correct in the browser fails in Cypress. Understanding why can save you hours of debugging. Follow these steps to troubleshoot:

    Step 1: Check If the Element Exists at the Time of the Test

    Cypress runs tests faster than the page may render. If the element isn’t present yet, the selector will fail. Use cy.wait() or .should('exist') to verify.

    Example:

    cy.get('#submit-btn').should('exist'); // ensures the button exists before clicking

    Step 2: Verify the Selector Is Correct

    Inspect the element in the browser and make sure the ID, class, or attribute matches. Remember, classes and IDs may change dynamically.

    Example:

    cy.get('.btn.primary').click(); // confirms the element has the expected classes

    Step 3: Avoid Selecting Hidden or Detached Elements

    Elements not visible or removed from the DOM cannot be interacted with by default. Use .should('be.visible') to debug or .click({ force: true }) if necessary.

    Example:

    cy.get('#hidden-btn').should('be.visible'); // checks visibility before interaction

    Step 4: Use More Specific Selectors When Needed

    If multiple elements match your selector, Cypress may target the wrong one. Combine selectors to make them unique.

    Example:

    cy.get('#login-form .btn[data-cy="submit"]').click(); // precisely targets the submit button inside login form

    Common CSS Selector Mistakes in Cypress

    Even experienced testers sometimes run into issues with CSS selectors. Knowing the common mistakes can save you from flaky tests, hard-to-find bugs, and wasted debugging time. Here are the key pitfalls to watch out for:

    • Relying on Dynamic or Changing IDs: Many modern web apps generate IDs dynamically. If you use these in your selector, your test might pass once and fail the next time the page loads. It’s better to use stable attributes or classes that don’t change between sessions.
    • Ignoring the Element’s Parent or Context: Selecting an element without considering where it sits in the DOM can cause Cypress to pick the wrong element, especially if multiple elements share the same class or type. Always check the hierarchy and use child or descendant selectors when necessary.
    • Targeting Hidden or Detached Elements: Cypress can only interact with elements that are visible and attached to the DOM. Trying to click or type on hidden elements will fail unless you explicitly force the action. Always verify visibility before interacting.
    • Using Overly Broad Selectors: Generic selectors like div input or .btn may match multiple elements, leading to unpredictable results. Tests become brittle and harder to debug. Make your selectors as specific as needed to target the correct element reliably.
    • Misusing Pseudo-classes or Advanced Selectors: Some CSS pseudo-classes or advanced selectors may not work as expected in Cypress. Using them can make tests unreliable. Stick to basic selectors, attribute selectors, and combinations, which Cypress handles consistently.

    Conclusion

    CSS selectors are the foundation of reliable Cypress tests. Choosing the right selector whether an ID, class, attribute, or combination lets you locate elements accurately, interact with them, and verify their styles or state. Avoiding common mistakes like dynamic IDs, overly broad selectors, or ignoring element visibility makes your tests more robust, maintainable, and less prone to errors.

    Ensuring your selectors work in real-world scenarios requires testing across multiple browsers and devices. Tools like BrowserStack allows you to validate your web app in real environments, across different browsers, screen sizes, and operating systems. This makes your tests more reliable and ensures your application behaves as expected for all users.

    Try BrowserStack for Free

    Data-rich bug reports loved by everyone

    Get visual proof, steps to reproduce and technical logs with one click

    Make bug reporting 50% faster and 100% less painful

    Rating LogosStars
    4.6
    |
    Category leader

    Liked the article? Spread the word

    Continue reading

    No items found.

    Put your knowledge to practice

    Try Bird on your next bug - you’ll love it

    “Game changer”

    Julie, Head of QA

    star-ratingstar-ratingstar-ratingstar-ratingstar-rating

    Overall rating: 4.7/5

    Try Bird later, from your desktop