# Bad value “false” for attribute “hidden” on element X.

> Canonical HTML version: https://rocketvalidator.com/html-validation/bad-value-false-for-attribute-hidden-on-element-x
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `hidden` attribute indicates that an element is not yet, or is no longer, relevant to the current state of the page. Browsers will not render elements that have this attribute. It's available on all HTML elements as a global attribute.

In HTML, boolean attributes like `hidden`, `disabled`, `readonly`, and `checked` follow special rules. Unlike attributes in programming languages where you might set a value to `true` or `false`, boolean attributes in HTML work by presence or absence:

- **Present** = the feature is on (e.g., `hidden`, `hidden=""`, or `hidden="hidden"`)
- **Absent** = the feature is off (the attribute is simply not in the markup)

This is a common source of confusion. Writing `hidden="false"` does **not** make the element visible. Because the attribute is still present in the markup, the browser interprets it as "this element is hidden." The actual string value `"false"` is ignored for the purpose of determining the boolean state. This can lead to frustrating bugs where elements remain invisible despite what looks like correct code.

According to the HTML specification, the only valid values for a boolean attribute are the empty string (`""`) or the attribute's own name (e.g., `hidden="hidden"`). Any other value, including `"true"` or `"false"`, is invalid and will trigger a W3C validator error.

### How the `hidden` attribute works with newer values

Starting with more recent updates to the HTML specification, the `hidden` attribute also accepts the value `"until-found"`. When set to `hidden="until-found"`, the element remains hidden but can be revealed by the browser's find-in-page feature or by fragment navigation. This is the **only** keyword value (besides the empty string and the attribute's canonical name) that changes the attribute's behavior. It does not change the fact that `"false"` is an invalid value.

### How to fix it

- To **hide** an element, add the `hidden` attribute with no value.
- To **show** an element, remove the `hidden` attribute entirely from the markup.
- If you're toggling visibility with JavaScript, use `element.hidden = false` (the JavaScript property, not the HTML attribute) or `element.removeAttribute('hidden')`.

## Examples

### ❌ Invalid: setting `hidden` to `"false"`

```html
<!-- The element is STILL hidden and the markup is invalid -->
<div hidden="false">You won't see this text.</div>
```

### ❌ Invalid: setting `hidden` to `"true"`

```html
<!-- "true" is also not a valid value for a boolean attribute -->
<p hidden="true">This paragraph is hidden, but the markup is invalid.</p>
```

### ✅ Valid: using `hidden` without a value

```html
<div hidden>This element is hidden from the page.</div>
```

### ✅ Valid: using `hidden` with an empty string or its own name

```html
<!-- Both of these are valid ways to write boolean attributes -->
<div hidden="">Hidden element</div>
<div hidden="hidden">Also a hidden element</div>
```

### ✅ Valid: showing the element by omitting `hidden`

```html
<div>This element is visible because it has no hidden attribute.</div>
```

### ✅ Valid: using `hidden="until-found"`

```html
<div hidden="until-found">
  This content is hidden but can be found via browser search.
</div>
```

### Toggling visibility with JavaScript

When dynamically showing or hiding elements, use the `hidden` property on the DOM element rather than setting the attribute to `"false"`:

```html
<button type="button" id="toggle">Toggle message</button>
<p id="message" hidden>Hello! Now you can see me.</p>
<script>
  document.getElementById("toggle").addEventListener("click", function () {
    const msg = document.getElementById("message");
    msg.hidden = !msg.hidden; // Correctly toggles the boolean property
  });
</script>
```

Using `msg.hidden = false` in JavaScript correctly removes the `hidden` attribute from the element. This is different from writing `hidden="false"` directly in HTML, which keeps the attribute present and triggers the validation error.
