My code works 100% as expected. All controls can be reached using the tab key or the arrow keys, except for the 2nd radio button, labeled "No screening", which is never reached.
Is there a simple solution to fix that or should I opt for a different UI layout?
See the code ...
/* Just some simple (Bootstrap) formatting. Nothing interesting. */
* {
padding: 3px;
}
.control-group {
margin-bottom: 5px;
}
.control-label {
font-weight: bold;
}
label {
display: inline-block;
}
.form-check {
padding-left: 0;
display: block;
min-height: 1.5rem;
margin-bottom: .125rem;
}
input {
margin: 0;
}
button {
border: 1px solid #000;
}
.btn {
display: inline-block;
text-align: center;
text-decoration: none;
vertical-align: middle;
cursor: pointer;
user-select: none;
}
.card.screening {
margin-left: 2rem;
width: 30rem;
padding: 10px;
}
.card {
position: relative;
display: flex;
flex-direction: column;
background-clip: border-box;
border: 1px solid #999;
}
.card-text:last-child {
margin-bottom: 0;
}
.top-spacer {
margin-top: 10px;
}
.note {
font-size: small;
}
<form action="process.php" method="POST">
<div class="control-group">
<label class="control-label">Reason upload *</label>
<div class="controls">
<div class="form-check">
<input type="radio" id="reasonUploadScreening" name="reasonUpload" value="screening" autocomplete="off" tabindex="0">
<label class="btn" for="reasonUploadScreening">Screening
<select id="screeningId" name="screeningId" class="field">
<option value="" disabled="" selected="">Select a screening</option>
<option value="20240328-1318">20240328-1318 John Doe (26-02-1968)</option>
<option value="20240328-1318">20240328-1604 [Anonymous]</option>
<option value="20240201-1575">20240201-1575 Jane Smith (11-11-1957)</option>
<option value="20240201-1100">20240201-1100 Peter Johnson (21-01-1980)</option></select>
</label>
<div class="card screening top-spacer">
<div class="card-text">
<div class="control-group">
<label class="control-label">Number of images *</label>
<div class="controls">
<input type="radio" id="numberOfImages2" name="numberOfImages" value="2" autocomplete="off">
<label class="btn" for="numberOfImages2">Two images (Single-field)</label>
<input type="radio" id="numberOfImages4" name="numberOfImages" value="4" autocomplete="off">
<label class="btn" for="numberOfImages4">Four images (Two-field)</label>
</div>
</div>
<div class="control-group">
<label class="control-label">Specify images *</label>
<div class="controls">
<input type="radio" id="specImgYes" name="specImg" value="1" autocomplete="off">
<label class="btn" for="specImgYes">Yes</label>
<input type="radio" id="specImgNo" name="specImg" value="0" autocomplete="off">
<label class="btn" for="specImgNo">No</label>
</div>
</div>
<div class="control-group">
<label class="control-label">Mydriatics (dilating eye drops) used *</label>
<div class="controls">
<input type="radio" id="mydriasisYes" name="mydriasis" value="%s" autocomplete="off">
<label class="btn" for="mydriasisYes">Yes</label>
<input type="radio" id="mydriasisNo" name="mydriasis" value="%s" autocomplete="off">
<label class="btn" for="mydriasisNo">No</label>
</div>
</div>
</div>
</div>
</div>
<div class="form-check">
<input type="radio" id="reasonUploadNoSreening" name="reasonUpload" value="noScreening" autocomplete="off" tabindex="0">
<label class="btn" for="reasonUploadNoSreening">No screening</label>
<div class="card screening top-spacer">
<div class="card-text">
<span class="note">Max. 200 images. The images will be visible to all users.</span>
</div>
</div>
</div>
</div>
</div>
<div class="control-group top-spacer">
<div class="controls">
<button value="submit" name="submit">Submit</button>
</div>
</div>
<p class="note top-spacer">Fields marked with * are required.</p>
</form>
The "No screening" along with "Screening" radio is the part of the "reasonUpload" group, and is skipped only when one of them is selected:
Example: "No screening" is skipped, because "Screening" is selected (need to use arrow keys):
/* Just some simple (Bootstrap) formatting. Nothing interesting. */
* {
padding: 3px;
}
.control-group {
margin-bottom: 5px;
}
.control-label {
font-weight: bold;
}
label {
display: inline-block;
}
.form-check {
padding-left: 0;
display: block;
min-height: 1.5rem;
margin-bottom: .125rem;
}
input {
margin: 0;
}
button {
border: 1px solid #000;
}
.btn {
display: inline-block;
text-align: center;
text-decoration: none;
vertical-align: middle;
cursor: pointer;
user-select: none;
}
.card.screening {
margin-left: 2rem;
width: 30rem;
padding: 10px;
}
.card {
position: relative;
display: flex;
flex-direction: column;
background-clip: border-box;
border: 1px solid #999;
}
.card-text:last-child {
margin-bottom: 0;
}
.top-spacer {
margin-top: 10px;
}
.note {
font-size: small;
}
<form action="process.php" method="POST">
<div class="control-group">
<label class="control-label">Reason upload *</label>
<div class="controls">
<div class="form-check">
<input type="radio" id="reasonUploadScreening" name="reasonUpload" value="screening" autocomplete="off" tabindex="0" checked>
<label class="btn" for="reasonUploadScreening">Screening
<select id="screeningId" name="screeningId" class="field">
<option value="" disabled="" selected="">Select a screening</option>
<option value="20240328-1318">20240328-1318 John Doe (26-02-1968)</option>
<option value="20240328-1318">20240328-1604 [Anonymous]</option>
<option value="20240201-1575">20240201-1575 Jane Smith (11-11-1957)</option>
<option value="20240201-1100">20240201-1100 Peter Johnson (21-01-1980)</option></select>
</label>
<div class="card screening top-spacer">
<div class="card-text">
<div class="control-group">
<label class="control-label">Number of images *</label>
<div class="controls">
<input type="radio" id="numberOfImages2" name="numberOfImages" value="2" autocomplete="off">
<label class="btn" for="numberOfImages2">Two images (Single-field)</label>
<input type="radio" id="numberOfImages4" name="numberOfImages" value="4" autocomplete="off">
<label class="btn" for="numberOfImages4">Four images (Two-field)</label>
</div>
</div>
<div class="control-group">
<label class="control-label">Specify images *</label>
<div class="controls">
<input type="radio" id="specImgYes" name="specImg" value="1" autocomplete="off">
<label class="btn" for="specImgYes">Yes</label>
<input type="radio" id="specImgNo" name="specImg" value="0" autocomplete="off">
<label class="btn" for="specImgNo">No</label>
</div>
</div>
<div class="control-group">
<label class="control-label">Mydriatics (dilating eye drops) used *</label>
<div class="controls">
<input type="radio" id="mydriasisYes" name="mydriasis" value="%s" autocomplete="off">
<label class="btn" for="mydriasisYes">Yes</label>
<input type="radio" id="mydriasisNo" name="mydriasis" value="%s" autocomplete="off">
<label class="btn" for="mydriasisNo">No</label>
</div>
</div>
</div>
</div>
</div>
<div class="form-check">
<input type="radio" id="reasonUploadNoSreening" name="reasonUpload" value="noScreening" autocomplete="off" tabindex="0">
<label class="btn" for="reasonUploadNoSreening">No screening</label>
<div class="card screening top-spacer">
<div class="card-text">
<span class="note">Max. 200 images. The images will be visible to all users.</span>
</div>
</div>
</div>
</div>
</div>
<div class="control-group top-spacer">
<div class="controls">
<button value="submit" name="submit">Submit</button>
</div>
</div>
<p class="note top-spacer">Fields marked with * are required.</p>
</form>
which is expected behavior:
When focus moves to the group in which a radio button is selected, pressing Tab and Shift+Tab keys move focus to the radio button that is checked.