Fieldsets
by stitot
HTML
<form>
<fieldset>
<legend>Parent 1</legend>
<fieldset>
<legend>Child 1.1</legend>
<input type="radio" id="kraken" name="monster" value="K" />
<label for="kraken">Kraken</label><br />
</fieldset>
<fieldset>
<legend>Child 1.2</legend>
<input type="radio" id="sasquatch" name="monster" value="S" />
<label for="sasquatch">Sasquatch</label><br />
<input type="radio" id="mothman" name="monster" value="M" />
<label for="mothman">Mothman</label>
</fieldset>
</fieldset>
<fieldset>
<legend>Parent 2</legend>
<fieldset>
<legend>Child 2.1</legend>
<div>
<input type="radio" id="kraken" name="monster" value="K" />
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster" value="S" />
<label for="sasquatch">Sasquatch</label><br />
<input type="radio" id="mothman" name="monster" value="M" />
<label for="mothman">Mothman</label>
</div>
</fieldset>
<fieldset>
<legend>Child 2.1</legend>
<div>
<input type="radio" id="kraken" name="monster" value="K" />
<label for="kraken">Kraken</label><br />
<input type="radio" id="sasquatch" name="monster" value="S" />
<label for="sasquatch">Sasquatch</label><br />
<input type="radio" id="mothman" name="monster" value="M" />
<label for="mothman">Mothman</label>
</div>
</fieldset>
</fieldset>
</form>
CSS
/* General fieldset styling */
fieldset {
border: 1px solid #ccc;
margin: 0;
padding: 0;
display: block;
overflow: hidden; /* Ensures content is hidden when collapsed */
}
/* Expanded fieldset */
fieldset:not(:disabled) {
max-height: none; /* Allow natural height */
padding: 10px; /* Add padding when expanded */
}
/* Collapsed fieldset */
fieldset:disabled {
max-height: 0; /* Collapse to zero height */
padding: 0; /* Remove padding */
}
/* Legend styling */
legend {
cursor: pointer;
font-weight: bold;
padding: 5px;
}
/* Arrow indicator for legends */
legend::after {
content: " ▼"; /* Down arrow for open fieldsets */
float: right;
}
fieldset:disabled legend::after {
content: " ►"; /* Right arrow for collapsed fieldsets */
}
JavaScript
document.addEventListener("DOMContentLoaded", () => {
const form = document.querySelector("form")
// Add click event listeners to all legends
const legends = form.querySelectorAll("legend")
legends.forEach((legend) => {
legend.addEventListener("click", () => {
const fieldset = legend.parentElement
// Toggle the clicked fieldset
const isDisabled = fieldset.hasAttribute("disabled")
if (isDisabled) {
const siblingFieldsets = Array.from(
fieldset.parentElement.children,
).filter(
(sibling) => sibling.tagName === "FIELDSET" && sibling !== fieldset,
)
siblingFieldsets.forEach((sibling) =>
sibling.setAttribute("disabled", ""),
)
fieldset.removeAttribute("disabled")
} else {
fieldset.setAttribute("disabled", "")
}
})
})
})