Follow-up to #2152217: Remove theme_form_required_marker() from the theme system - use CSS instead
Updated as of #165.
Problem/Motivation
3 years ago, in #2152217: Remove theme_form_required_marker() from the theme system - use CSS instead, the community decided to remove the star (*) used to indicate that a form field is required from the source code to add it from the CSS. Initially, the issue was just about converting the theme function to a Twig template but changed quickly. The purpose of this change was to simplify theming and improve accessibility. The thing is that, according to WCAG, this is not as accessible as we thought.
References:
- WCAG 2.0 - 1.1.1 Non-text Content
- F3: Failure of Success Criterion 1.1.1 due to using CSS to include images that convey important information
- WCAG 2.0 - 1.3.1 Info and Relationships
- Accessiweb 2.2 - Criterion 10.2 - [Bronze] On each Web page, is visible content still available when style sheets or images are disabled? (Accessiweb is the French accessibility standard)
F87: Failure of Success Criterion 1.3.1 due to inserting non-decorative content by using :before and :after pseudo-elements and the 'content' property in CSS. [The latest version of this document says that it is obsolete.]
Steps to reproduce:
Standard cases
- Go to any page including a form with required fields (eg. /user/login)
- Disable CSS in your browser
With JavaScript states API
Note: This mimics the automated test.
- In
settings.local.php, uncomment the line$settings['extension_discovery_scan_tests'] = TRUE;, or add that line tosettings.php. - Enable the
form_testmodule. - Go to
form-test/javascript-states-form. - Check the checkbox named "Checkbox trigger".
- Find the textfield named "Textfield required when checkbox trigger checked", and note the required marker (star / asterisk).
- Disable CSS.
- Find the textfield named "Textfield required when checkbox trigger checked" again.
Current result: the stars on field labels are absent and there is no other visual indication that the field is required
Expected result: there is still some visual indication about the status of the required field
Screenshots
| With CSS | Without CSS | |
|---|---|---|
| Before patch | ![]() |
![]() |
| After patch | ![]() |
![]() |
Proposed resolution
- Bring back markup, but use the string
"(required)"instead of"*"(aka, an asterisk or star). - Wrap the new markup in a
spanwith both:- The
hiddenCSS class to avoid changing the current look of the existing sites. aria-hiddento avoid screen readers to vocalize the content of thespan, as it's already covered by thearia-requiredand HTML5requiredattributes.
- The
- Put that
spaninside form labels and other interactive elements to increase target size. - Apply these changes to the following elements. In some cases this will result in duplication of the
"(required)"string with the same on the child field labels, but this is acceptable.- All standard form element labels.
legendelements (insidefieldset).summaryelements (insidedetails).- The
h4element that precedes datetime fields. - The JavaScript states API (as a JavaScript theme function in
core/misc/states.js).
See options 1 and 2 below for details on the different proposed implementations.
- Update tests & add coverage as needed.
Implementation options
Option 1: Append the text in template files. https://git.drupalcode.org/project/drupal/-/merge_requests/12981.Option 2 was chosen in #174.
This MR was RTBC until #156.
@larowlan supports this option.- Option 2: Append the text in the PHP render chain. https://git.drupalcode.org/project/drupal/-/merge_requests/15924.
@catch, @smustgrave, @kentr support this option. @larowlan didn't report concerns with the code in the MR.
Discussion starts at #154.
Remaining tasks
| Task | Novice task? | Contributor instructions | Complete? |
|---|---|---|---|
| Create a patch | Instructions | Done #19 | |
| Update the issue summary | Instructions | Done | |
| Apply changes to new Default Admin theme | Done #116 | ||
| Add automated tests | Instructions | Done | |
| Draft a change record for the API changes | Instructions | Done #128 | |
| Update the MR to incorporate feedback from reviews | Instructions | Done | |
| Update the MR to incorporate point #2 from #62. Other element types in JavascriptStatesTest may need coverage. |
Instructions | Done #130 | |
Refactor the $label.append(...) code in states.js into a JavaScript theme function (#62, point 5) |
Done #130 | ||
| Manually test the patch | Novice | Instructions | Done #19 |
| Fix cases of missing space in name / label (#125). The case displayed in #125 is states.js. |
Done #130 | ||
| Manually test the patch, specifically regarding the JavaScript states API. See the Steps to reproduce for details. |
Novice | Instructions | Done #150 |
| Add steps to reproduce the issue | Novice | Instructions | Done #97 |
| Embed before and after screenshots in the issue summary | Novice | Instructions | Done |
| Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards | Instructions | Done | |
| Decide if we're preceding with Option 1 or Option 2. Discussion starts at #154. |
Done. Option 2 was chosen in #174 |
User interface changes
Visually nothing as long as you have your CSS enabled. Before / after screenshots for visual regression are below.
A new "(required)" mention will be present on form field labels, fieldset legends, and details summaries for people that do not have their CSS enabled.
API changes
None.
Data model changes
None.
Before / after screenshots
Before and after screenshots illustrating that this MR isn't introducing any regressions (per request in #62 point 4)
Claro

Olivero

Admin theme

| Comment | File | Size | Author |
|---|---|---|---|
| #184 | media.jpg | 36.12 KB | rkoller |
| #162 | 2921627-160-login-form-translation-result-hebrew.png | 21.39 KB | kentr |
| #160 | interdiff.2921627-160.MR-12981-MR-15924.txt | 35.67 KB | kentr |
| #158 | 2921627-158-user-edit-page-with-Hebrew-language-installed.png | 109.26 KB | kentr |
| #156 | rtl.jpg | 258.17 KB | rkoller |
Issue fork drupal-2921627
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:




Comments
Comment #2
duaelfrComment #3
duaelfr@andrewmacpherson did a screenshot of the installer without CSS.
Comment #4
mgiffordThanks @DuaelFr - this is an interesting issue and one that we obviously didn't fully consider when making this change.
I think that part of this was the confidence that we are already providing a lot of semantic information for assistive technology users.
So in this case the semantics should be covered by both required="required" aria-required="true":
<input class="js-text-full text-full form-text required" data-drupal-selector="edit-title-0-value" id="edit-title-0-value" name="title[0][value]" value="" size="60" maxlength="255" placeholder="" required="required" aria-required="true" type="text">It is also interesting that the text is a symbol '*' rather than a word like '(required)'. So the meaning is already symbolic in the Drupal 7 way of addressing this.
I am pretty sure that there hasn't been any testing done without any CSS, I do wonder what other errors we'll catch by doing so. I do wonder though if perhaps this is an overly generalized guideline. Are people finding this a barrier? Is disabling CSS still relevant? It's probably more common to disable JavaScript, but there's lots that you can't do in any modern system without enabling it.
Are people in D8 theming the required element more now? Would everyone just be as happy if we'd kept it like we did in D7?
Comment #5
duaelfrSince screen readers are already using the
aria-requiredand the html5requiredattributes to vocalise the mandatory status of the field, anything we may add in the markup should be marked asaria-hiddenandspeak: noneto avoid the noise. Given that, we could just go back to the exact same markup than D7 which used<span class="form-required" title="This field is required.">*</span>. This way, themers could still hide the common star and use CSS to put their own required style. We keep accessibility AND themability.(IMHO, we should consider to use another class on this span that could be easier to target than this generic one.)
Comment #6
andrewmacpherson commentedWhy speak: none? aria-hidden should be enough to hide it from AT.
I can't find any info about speak:none implementation. I'd forgotten about the CSS speech properties. I don't think I've heard them being recommended any time recently.
Comment #7
andrewmacpherson commentedHow about just "required", to keep the wording short?
Comment #8
mgiffordSo we could just add something like this:
<label for="edit-account-name" class="js-form-required form-required">Username <span class="hidden">(required)<span></label>So that if there is no CSS, the HTML would look like "Username (required)". If CSS is read then it would be hidden. No need to use any aria-hidden elements at all.
That work?
Comment #9
duaelfrIMHO you can use a screen reader AND have no CSS so aria-hidden is required :/
Comment #10
mgiffordYes, but in the case of a screen reader user disabling CSS they would still get very clear verification that this was a required field and should sound like - "Username (required)". I'm not sure what the aria adds. If CSS is disabled they wouldn't get the '*' but they would get the text '(required)' which is good if not better.
Comment #11
duaelfr@mgifford The thing is that screen readers are already translating aria/html5 attributes to something. We need to hide this new string from them in any case to avoid a double indication. To summarize, we would need something like:
<label for="edit-account-name" class="js-form-required form-required">Username<span aria-hidden="true" class="hidden"> (required)<span></label>Doing this way:
Comment #12
andrewmacpherson commented#11 is on the right track.
I think it should work well for sighted screen reader users too. With CSS they will see an asterisk, and hear "required". Without CSS they see and hear "required" (in English, anyway).
There might a localization issue here. What if an operating system or screen reader localization announces the required attribute using one phrase, but Drupal localizes "required" as a different phrase? Like the difference between "mandatory" and "compulsory". I've never used a screen reader in any language other than English, so I don't know. It's beyond our control though.
A minor point: the span doesn't need to be inside the label - it won't form part of the accessible name for assistive tech either way. For all the scenarios in #11, the following pattern also works:
<label for="edit-account-name" class="js-form-required form-required">Username</label><span aria-hidden="true" class="hidden"> (required)<span>The difference between the two is that in #11 the word required is clickable, but in this version it isn't clickable.
Comment #13
duaelfrI think it's important to have it clickable. The wider the clickable area is, the more accessible the form is for people that are not necessarily click-snipers. :)
Plus, I feel it's more complicated to pur it outside the label (#suffix ?) than to append it in the label.
Comment #14
andrewmacpherson commentedI don't mind either way, so let's put the span inside the label as a safer default.
In D8 I think this goes in
form-element-label.html.twigwith no need for FAPI#prefix. Themers can still move it outside the label, or move it up to theform-element.html.twigtemplate if they like. Something like:We should probably include a comment to document why it's there for accessibility.
Comment #15
mgiffordComing along nicely! @andrewmacpherson & @DuaelFr
Comment #16
duaelfrHere is a patch to trigger the testbot.
I tried to find some place in core where the label render is tested but I found nothing. We are probably going to need to extend the coverage.
Comment #17
andrewmacpherson commentedThanks DuaelFr. The approach in patch #16 looks good, does what we discussed so far.
However we're not normally allowed to change templates in Stable and Classy themes during minor releases. Tagging for Stable and Classy maintainers - we've made changes to Stable to fix accessibility bugs before, so maybe this will qualify. Otherwise, we'll have to copy the Classy template to Bartik and Seven, and leave the Stable and Classy templates unchanged.
Nitpick: there's an extraneous space here we could eliminate. The one between the opening SPAN and the opening twig
{{The templates could be more readable if we split the "if required / endif" accross several lines, and used the whitespace collapsing form of braces:
{{- if required -}}. See Whitespace control in the Twig manual.Before going ahead with this, it would be good to test with a wide variety of browser + screen reader combinations. Screenshots of with and without author CSS applied will help here too.
Comment #18
andrewmacpherson commentedIf we aren't allowed to change Stable/Classy, a change record will be a good way to recommend this approach for contrib/custom themes.
Comment #19
duaelfr#17: I'm not sure about removing this space. The purpose is that people that browse without CSS should be able to read the label properly so we need a space to separate the label from the required mention. But, people that use CSS shouldn't have a lonely space at the end of their label for front-end-sake reasons. That's why I included this space in the span, the same way it's done for the "read more" link for example.
Here is a new version, aimed for template readability. I did some manual testing and the markup is exactly the same as the one in the #16's patch.
Markup
Before patch:
<label for="edit-name" class="js-form-required form-required">Username</label>After patch:
<label for="edit-name" class="js-form-required form-required">Username<span aria-hidden="true" class="hidden"> (required)</span></label>Screenshots
Comment #20
duaelfrUpdated IS to include the tasks table, the screenshots and update the proposed solutions.
Comment #21
andrewmacpherson commentedOverall, the progress is looking great!
The extra space - ignore me. Now I see that only one of those spaces is actually output. That's fine, the output is correct.
We're still updating Stable and Classy templates though. I'm expecting the front-end framework managers will say no to that.
Comment #22
duaelfrI hope they won't as these changes has absolutely no visual effect and they are important for a11y :/
Comment #23
opiWhy use
.hiddenclass and not.visually-hidden?Comment #24
duaelfrBecause we need that string to NOT be read by screen readers. They already inform their users that the field is required because of the
aria-requiredandrequiredhtml attributes.Comment #25
andrewmacpherson commentedRe: #23 and #24 - This is about avoiding verbosity in assistive tech, e.g. screen readers announcing "required" twice. The use of
aria-hidden="true"is sufficient to ensure that span is hidden from AT, regardless of whether author CSS gets applied or not. So in this sense it doesn't really matter whether we use.hiddenor.visually-hidden.I think we should stick with
.hiddenfor a couple of reasons:.hiddenwill effectively hide it from legacy browser/AT combinations which don't supportaria-hidden, but.visually-hiddenwon't..hiddenis a much simpler (safer) implementation than.visually-hidden. It just usesdisplay:noneinstead of all the properties needed for the 1px clip technique. Note that the.visually-hiddenCSS itself needs ongoing review for nest practice. (See #2819823: CSS clip deprecated - .visually-hidden needs an update?.)Comment #26
andrewmacpherson commentedWe'll need to address this in
fieldset.html.twigtoo, to achieve the same effect for required FAPI radios and checkboxes.Some core forms where you test this:
admin/structure/book/settings, which has required'#type' => 'radios'and'#type' => 'checkboxess'.admin/config/workflow/workflows/manage/editorial/add_transition.Comment #27
andrewmacpherson commentedComment #28
andrewmacpherson commentedThe patches so far have modified templates in Stable and Classy. We'd like to know if this will be allowed, or whether to update Seven and Bartik instead.
Comment #30
andrewmacpherson commentedI noticed a similar pattern in the wild, on Expedia's forgot-password form.
Here's a screenshot of the form and markup, from Firefox's dev tools. It's not exactly the same as proposed here, but works on similar lines. The main difference is that they are using a visually-hidden approach to the "required" text hint, and are not using aria-hidden. A screen reader says the word "required" twice; from the label text, and from the required HTML attribute.
Without CSS, the label reads "Email addressrequired", without any space between words. Not bad, but our patch is already doing better:
I'm glad to see other people are thinking along the same lines as this issue. The patch here is a bit higher quality than Expedia's implementation, in my view.
Comment #31
duaelfrStarting to work on #26
Comment #32
duaelfrWhile fixing fieldsets, I thought about details elements too.
Comment #34
duaelfrI forgot I had to patch for 8.5 first so Seven does not have the details.html.twig template yet.
Comment #36
duaelfrNew patch that fixes tests and extends the issue to the datetime wrapper that I forgot before.
Comment #38
duaelfrI simplified the failing test assuming that fieldsets labels were tested elsewhere.
I added some coverage for our new markup in fields, fieldsets and wrappers.
I did not find tests for datetime_wrapper so it stays out of coverage (maybe we should consider not altering these templates).
Comment #40
duaelfrLet's try this way!
Comment #42
duaelfrI know, I should have a local env for testing but I don't for now :/
Comment #44
weekbeforenextJust tested core_accesible_form_labels-2921627-42.patch on Drupal Core 8.6.0-rc1 and it looks like it's working.
Comment #45
mikelutzComment #46
kostyashupenkoon my side i can apply #42 patch agains 8.6.x branch
Comment #47
mikelutzRe-rolling this for 8.8
Comment #48
pcate commentedWill this patch apply the correct markup when the required attribute is toggled via the JS states API?
Comment #50
sutharsan commentedRe-roll #47 patch for latest 8.9.x
Comment #51
sutharsan commentedThis patch makes 'required'
#statesadd the right markup.Comment #54
sutharsan commentedUnder certain conditions the marker gets added multiple times.
Comment #56
andrewmacpherson commentedBumping to major, because some of the relevant WCAG success criteria are at level A. In particular, the presence of the "required"/asterisk counts as "3.3.1. labels and instructions". If you don't know it's required, you don't have full instructions.
I was chatting with @rainbreaw about another potential use for this is in Windows high-contrast mode. Instead of trying to get an asterisk to display in
:after, Windows high-contrast mode could use the actual required text (i.e. don't hide it).Comment #57
andrewmacpherson commentedComment #58
vsujeetkumar commentedFixed test, Please review.
Comment #59
vsujeetkumar commentedPlease ignore my previous patch, fixed test, Please review.
Comment #60
sulfikar_s commented#59 , I've applied this patch and is working properly. I've attached the before and after screenshots below.

Before patch,
After patch,

Comment #61
sulfikar_s commentedComment #62
lauriiiWhy do we need these changes?
Can we add test coverage for this?
We should add a theme function for this
Comment #63
sutharsan commentedRerolled the patch for 9.2.x
Comment #64
sutharsan commentedStatus to 'Needs review' to verify the reroll did not introduce errors.
Comment #65
duaelfrThe patch applies on 9.3 and still does what's expected.
What are the next steps to move this forward?
Comment #66
gauravvvv commentedThis patch needs Reroll, as it has changes in
/core/misc/states.jsfile but/core/misc/states.es6.jsfile is not updated.Update es6 file then compile the code with yarn.
Comment #67
wim leersFor #66.
Comment #68
vsujeetkumar commentedAddressed #66, Please have a look.
Comment #69
duaelfrLooks good to me.
All comments have been addressed.
Patch passes all tests and fixes the issue.
Let's get it commited!
Comment #70
quietone commentedBug fixes are against the latest version and the patch does not apply to 9.3.x. :-(
Comment #71
ankithashettyRerolled the patch in #68, thanks!
Comment #74
duaelfrRerolled for 9.4
Comment #75
ranjith_kumar_k_u commentedFixed CS error.
Comment #80
mgiffordHopefully we can get this patch re-built and bring this change into Core.
Comment #81
gauravvvv commentedI have attached the patch for 11.x-dev. As in the earlier patch #75, Classy, stable and bartik were updated. which are no longer part of core. I have updated the latest themes. please review
Comment #83
mgiffordAlternatively, there's this approach https://adamsilver.io/blog/how-to-highlight-required-and-optional-form-f...
Just mark the optional fields. This would be a pretty huge change in the forms design though. Definitely a major release change, but D11 could be it.
Comment #84
ranjith_kumar_k_u commentedRemoved some unrelated changes and added new tests
Comment #85
ranjith_kumar_k_u commentedComment #86
smustgrave commentedThis is having to update existing templates. Is that needed?
If there really is no other way then a change record will be needed.
Comment #87
mgiffordAdding reference to Windows High Contrast Mode.
Comment #88
duaelfr#86: yes we have to update existing templates or the issue won't be fixed. Adding the tag.
Comment #90
duaelfrRerolled #84 on the last 11.x commit in a MR.
Here is the patch for composer.
This issue still needs a Change Record. Is there a native english speaker that could handle this?
Comment #91
kentr commentedLooks like STR is still needed.
Adding Novice tag so novices can find this for those todo items in the IS.
Are tests still needed, or can that todo item be marked as done?
This point about WHCM (aka, forced-colors) by @andrewmacpherson in #56 hasn't been addressed. Is that intentional?
Comment #92
duaelfrJust rerolled MR on latest 11.x
Patches attached for composer
Comment #93
kentr commentedIt looks like point #4 in #62 by @laurii hasn't been addressed. I don't see the screenshots from all core themes, at least. I'd say Gin should also be tested b/c it's in CMS and going into core.
Did the other points get addressed? I didn't see a reference to that comment in subsequent changes.
Comment #94
prudloff commentedComment #95
rkollerFrom a manual testing standpoint this looks good across themes - tested in Claro 11.x, Gin 5.0.x, and Olivero 11.x. Instead of screenshots I went with short videos to compare with and without CSS to illustrate the visual output as well as the output of the the aural interface.
The only detail I wonder is something we've raised in #2852874-24: [Meta] Set the required state for all fields in Core in the Accessibility Object Model (AOM) (see point 2). As you can see and hear in the three videos, the star is getting announced in the aural interface alongside the announcement of the required attribute, strictly speaking that is redundant information - basically distracting noise. so i wonder if it would make sense to fix that detail within the scope for this issue? cuz the linked issue is only about the file field type and would have required a followup issue for in general anyway? or should it be moved to a dedicated followup?
Comment #96
mgiffordI don't think we need screenshots any more, as the video @rkoller produced should be fine
We still need:
Comment #97
duaelfrUpdated the IS to add steps to reproduce.
Rerolled the MR on the last 11.x.
Added a fix to remove the "star" from aural output using the alternative text capability of the content CSS attribute.
This last fix would need a double check because it applies on fieldset labels too. As they are not marked as required by an HTML attribute, we might need to keep the aural output on these.
The issue still needs a change record (I'm not a native speaker, so I don't feel comfortable with that task)
Comment #98
rkollerawesome thanks so much @duaelfr for the fast incorporation of that additional fix! i did another round of manual testing and recorded again for claro, olivero, and gin in safari 26.2 on macos 26.2 and in addition to that i also tested in the latest version of firefox and edge - using drupal 11.x and for testing with gin, gin 5.0.x with gin_toolbar installed.
claro and olivero look perfect to me in testing and the recorded videos. for firefox and edge i had the exact same results. perfect from my point of view. the only thing in gin the latest changes in regard to the star excluded from the aural interface are not available (the rest of the fixes still are still there as you can see ). not sure if something is missing for this MR or in case of the exclusion of the star from the aural interface an additional fix in gin would be necessary?
Comment #99
kentr commentedThere were some random test failures that passed when re-run. Pipeline is green.
@rkoller
AFAICT that star comes from Gin's CSS (from a quick inspection in the browser with Gin
5.0.10).Comment #100
rkollerah nice thanks! so if the star comes from gin that means a followup in the gin queue would be necessary to get en par with claro and olivero. then this issue would be good to go, isnt it?
Comment #101
kentr commented@rkoller
I agree that a followup for Gin is needed.
If you create the issue and the STR, I'm happy to add a screenshot that shows the CSS for this MR being overridden by Gin. I'm also happy to detail that in the proposed resolution, if that's helpful.
Comment #102
rkoller@kentr i've opened #3566851: [PP-1] Avoid announcing the star for required fields in the aural interface . feel free to update the issue summary in case i've missed anything or phrased it in a to complicated manner. and at first i thought it might be good to postpone the followup on this issue but strictly speaking it could run in parallel if gin is overriding Claro CSS anyway?
Comment #103
kentr commentedComment #104
rkollerok after quite a few discussions with @kentr and @mgifford we came up with the following approach. first a bit of context. this issue would be ready to go. problem is due to the introduction of the fix for removing the start from the aural interface based on my suggestion in https://git.drupalcode.org/project/drupal/-/merge_requests/12981/diffs?c... this issue would be blocked by #2852874: [Meta] Set the required state for all fields in Core in the Accessibility Object Model (AOM). by removing the star fields that dont have a programmatic required label would be unidentifiable for screenreader users. :( and it turned out in my testing that not only the field is missing the required attribute but also:
so our consensus was the following:
so to summarize the sole step relevant for the current issue is roll back https://git.drupalcode.org/project/drupal/-/merge_requests/12981/diffs?c... , do a last recheck, finish the change record, and then this issue should be ready for RTBC imho- apologies for the back and forth :(
Comment #106
duaelfrMR rerolled on main branch.
Last commit reverted as asked in #104
Patch attached for composer.
Comment #107
rkoller@duaelfr. thank you for reverting the last commit and apologies again for the back and forth. i just went ahead and retested the latest state of the MR. i've noticed one detail I haven't thought of in my previous test that raises one question. I have tested now a node edit form that contained a file and an image field around others that all were set to required. those fields are wrapped in field sets and the label of those field sets have stars too. The question is should those fieldset labels also replace the star with
(Required)? At the moment only the star is not displayed anymore with CSS unavailable:Comment #108
smustgrave commentedAppears to have some test failures.
Also will need a change record for the template changes.
Thanks!
Comment #109
kentr commentedI'll look into the test failures.
Comment #110
kentr commentedComment #111
kentr commentedThe test failures in the previous pipeline were random.
As part of a rebase, I omitted
core/modules/contact/tests/src/Functional/ContactSitewideTest.phpin the original patch because it has since been removed inmain.Concern regarding tests:
#38 says
However, the MR has changes to several instances of
datetime-wrapper.html.twig.Some of them were added in #84, but I can't tell from the patch if it adds coverage directly related to
datetime-wrapper.html.twig.Looking into it further, but for now +Needs tests.
Comment #112
kentr commentedLooks like the changes need to be applied to the new Admin theme.
I will look into that, also.
Comment #113
kentr commentedOther concerns:
1. Regarding
fieldset(#104#107) and the file and image fields in the screenshotsCurrently, in Claro, those aren't
fieldsetelements. They'redetails/summaryelements.However, the MR does add the "(required)" text for
fieldsetelements.So the question is, do we actually want that for
fieldsetelements? Because actual labels for individual fields also have "(required)".I'm seeing this also on required Datetime fields in the Stark theme, which uses the base system template that arbitrary themes might use if they don't override it.
2. Regarding
datetime-wrapper.html.twigPer #111, several instances of
datetime-wrapper.html.twigare modified.These changes are evident with required Timestamp fields, again in Stark theme.
To me, the change creates a problem. It adds the "(required)" text to
h4elements above the actual input fields, and the fields themselves also have "(required)". So, my thought is thatdatetime-wrapper.html.twigshould not be modified for this issue.What are thoughts on these points?
[edited to fix typos & improve formatting]
Comment #114
kentr commentedHere's a side-by-side screenshot of required datetime, timestamp, and file fields with and without CSS in Claro.
Now it makes more sense why the required marker (aka the asterisk, or "star") was added for the
legendand theh4in the datetime wrapper: the individual field labels are visually hidden.Olivero and Admin (the theme formerly known as Gin, or TTFKAG) also do this.
However, since the individual fields do have the text "(required)", as seen in the right side of the screenshot, it seems unnecessary to also add "(required)" to the
legendand theh4in the datetime wrapper.Comment #115
kentr commentedDisregard my comments about changing
fieldset.html.twiganddatetime-wrapper.html.twig. I had forgotten about #26, and I understand the date fields better now.I'll add detail to the IS.
IMO it also needs before / after screenshots of radios, checkboxes, and the different date/time field types. I will add these.
I think a followup is required for timestamp fields. My sense is that they should actually be in a
fieldsetbecause they consist of two related fields.Comment #116
kentr commentedsummaryelements, but they had not been done in Claro or Olivero yet. Now they are.legendandsummary.The others I saw in the MR, in
\Drupal\Tests\system\Functional\Form\ElementTest::testRequiredFieldsetsAndDetails(), only apply to thestarterkit_theme. It looks like applying that test file tostarterkit_themewas intentional for #3304731: Update remaining tests using Classy to use Starterkit , so I left it as-is.datetime-wrapper.html.twig.Comment #117
kentr commentedForgot to mention that I also added test coverage fordatetime-wrapper.html.twig.Attaching before / after screenshots with more fields in Claro, Olivero, Admin theme. As these are for visual regression checks, not to demonstrate the changes, the left & right sides of each should be identical.
[edited for clarification]
Comment #118
kentr commentedComment #119
rkollercreated again another content type containing every available field in core and created with and without css screenshots on the node edit form with claro, admin, and olivero, plus the same for the login page.
over all this looks good to me from a manual testing perspective, excellent work @kentr thank you! the only detail i consider odd are the stars on the fieldsets and then on the fields within that fieldset again - potential scenarios, sometimes a single field, sometimes several, sometimes every field within. but that is something that could be solved within #3174459: [PP-1] W3C Validation: required attribute not allowed on fieldset tag . that is out of scope for this issue imho.
Comment #120
rkolleradded some context to the before and after screenshots section in the issue summary
Comment #121
kentr commented@rkoller
In your opinion, can we mark it as RTBC after the draft change record is added?
Comment #122
kentr commentedStill needs a change record.
If anyone thinks that's doable by a novice, please add the Novice tag.
Comment #123
kentr commentedI'm working on a change record.
I also want to confirm that all of #62 has been addressed. In particular, I'm not certain that point 5 was addressed.
Comment #124
kentr commentedThink it needs some additional assertions for JavaScript states.
Comment #125
kentr commentedAdded STR for cases using the JavaScript states API.
There are cases where the space is missing between the "(required)" text and the main part of the accessible name. Here's a screenshot showing that.
Comment #126
kentr commentedAdded a draft CR. It needs some work.
Comment #127
kentr commentedComment #128
kentr commentedUpdated the CR with before / after examples for template modifications.
Comment #129
kentr commentedWorking on the other code and test changes.
Comment #130
kentr commentedAddressed the code items in Remaining tasks.
I think it needs additional manual testing just for the JavaScript states API. See the Steps to reproduce for details.
Comment #131
kentr commentedI just pushed the update that I meant to push before my last comment...
Comment #132
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #133
kentr commentedI'll rebase it.
Comment #134
kentr commentedRebased and passing.
Comment #135
mherchelJust a drive by here (sorry!).
I haven't read through the full thread, but I did look at the MR.
There may be an easier way to do this. We could do something like this with CSS only:
See https://www.stefanjudis.com/today-i-learned/css-content-accepts-alternat...
Comment #136
mherchel...but it wouldn't be translatable (unless we add it via JS)
Comment #137
kentr commented@mherchel
Thanks for looking!
Were you saying to use CSS only instead of adding actual text in the markup?
If so... One of main goals is to have the textual "required" present in cases where CSS is disabled. That's what the "not use full CSS" refers to...
Comment #138
kentr commentedComment #139
mherchelTBH, I think my idea is dead in the water because of lack of translation. If we went with JS, it would add a lot of complexity.
Comment #140
kentr commentedComment #141
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #142
kentr commentedI'll rebase it.
Comment #143
kentr commentedRebased and passing.
Comment #144
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #145
rkollerLooks like the tests still pass? I've checked out MR12981 and went through a node edit form containing all available field types in core another time. Tested that node edit form with Claro, Default Admin, and Olivero - all looked good to go. The output of the required label on fieldsets will be covered in #3174459: [PP-1] W3C Validation: required attribute not allowed on fieldset tag . A Change Record that looks good and complete is available at https://www.drupal.org/node/3580406 and the issue summary is also in a good shape in general. Not sure why the need review bot reverted the issue back to needs work? From my perspective in case there isnt anything ive missed in regard to failing tests, this issue looks good to go and ready for RTBC?
Comment #146
kentr commentedI'll rebase it.
Comment #147
duaelfrEverything still looks good.
Tests are green, code has been reviewed multiple times, manual reviews has been done extensively and a change record has been written.
Let's go!
Comment #148
kentr commentedI believe it still needs manual testing for the JavaScript states case (#130).
Comment #149
kentr commented^^ See the Steps to reproduce for details.
Comment #150
rkollerGood point, thanks for the reminder, missed that detail. I've quickly tested for Javascript States pointed to in #148... Works in latest Safari, Firefox Developer Edition, and Edge:
The rest still looks good to go as well. Setting back to RTBC
Comment #151
kentr commentedComment #152
kentr commentedAdded
a11y-bugsmashtag.Comment #153
quietone commentedRemoving the 'Drupal should' from the title because that is redundant since this is the Drupal core queue.
The change record clearly shows what developers/themers should for the templates changes, which is great to see. I moved some text around at the beginning to put the change first, which is the preferred style.
I updated credit.
Comment #154
kentr commentedI don't mean to rock the boat, but now that I've seen a mechanism for appending text to labels / names without modifying templates, I'm wondering if that's a better approach.
Adding the '(required)' text in templates means that existing sites with custom templates have to update their templates, and also carries the risk that it will get accidentally removed from custom templates during their lifespan.
As an alternative, it may be possible to add the text in a
::preRender(), similar to how it is done for #2848507: Indicate that grouping elements have child element errors for ux and a11y:I also wonder if translating the full string like this instead of just the '(required)' text by itself yields a better translation result for some languages.
I'm curious to hear others' opinions.
Comment #155
catchI think it's worth exploring #154, if we can handle it centrally that will save updating a lot of templates, work for contrib, and agreed it's likely to be a lot better for translation. I also think appending (required) won't necessarily work for RTL languages - was that tested?
Comment #156
rkolleruhhh damn, good point about RTL, at least i had forgot testing that as well. i have caught up on that oversight of mine and just tested with the current state of the MR. just switched to hebrew and the
(Required)tag is to the right of for example the username label, that should be on the left insteadComment #157
smustgrave commentedKentr asked about this on the side and agree with a non template approach.
Comment #158
kentr commentedI'll work on the changes.
I tested before with a Hebrew translation file imported manually via the languages UI, and again just now with the current MR.
The text "(required)" is to the left of the Hebrew, between the input and the Hebrew.
Here's a screenshot of the user edit page with Hebrew set as the default language. It should be the same fields as in @rkoller's screenshot, I think, but a Hebrew reader would have to confirm.
I can't say why English in RTL doesn't work this way in @rkoller's screenshot. It might have something to do with the difference between a language and a script. My understanding is that languages aren't RTL, but rather it's the script that is RTL.
Comment #160
kentr commentedThe MR with the new strategy is for review. I'm hiding the other MR for now.
I think it would be best to get approval on the general code strategy before more manual testing:
#pre_rendercallback method toFormElementBase.This method appends "(required)" to
#titlewhen the criteria are met.Use a
#pre_rendercallback because AFAICT it must be done after validation so that the unmodified#titleis used for validation error messages.FormBuilder::handleInputElement().These are elements which for which
$element['#input']isTRUE.DetailsandFieldset, add the new#pre_rendercallback explicitly in the element's::getInfo()method.Other notes
Labelrender element, and I added code for it to work. I think it was previously working because it uses the same template as automatic labels.states.js, I changed the logic a little to use adata-drupal-requiredattribute on thespaninstead of the CSS classjs-required.This is because I wanted to make the PHP and JavaScript versions the same in order to have only one version of the string for translation, and it seems inappropriate to add
js-requiredto an element in PHP.It also seems less likely that someone will remove the
data-drupal-requiredattribute than ajs-requiredclass.The string shows up in the translation interface as
@title <span aria-hidden="true" class="hidden" data-drupal-required> (required)</span>, which sounds like what we want based on the translation documentation.Here's screenshot of the login form with a translation entered for Hebrew (CSS is disabled).
[edit: added a link to relevant code in the MR]
Comment #162
kentr commentedTagging for subsystem maintainer review to get feedback on the strategy in #160.
Also uploading the image again. It doesn't appear to have saved.
Comment #163
kentr commentedComment #164
smustgrave commentednot a forms maintainer but like this approach a lot better then before!
Comment #165
larowlanLeft a comment on the option 1 MR as to why I personally prefer that one.
Comment #166
kentr commented@larowlan, thanks for the review and the comments on the MR. I replied in the MR regarding the drawbacks that I see on Option 1.
Also WRT drawbacks, @catch said this about a non-template approach in #155:
Not sure what's next for this.
It looks like @larowlan didn't have any concerns about the code in the MR for Option 2.
Option 1 would be RTBC except for #156. However, in my testing (#158) the new text was to the left of the main label as expected. I don't know if that satisfies #156 and qualifies for RTBC.
I rebased the MR for Option 1 (https://git.drupalcode.org/project/drupal/-/merge_requests/12981).
I suspect further manual testing should wait until it's clear which approach we're taking.
Comment #168
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #169
kentr commentedI'll rebase it.
Comment #170
kentr commentedRebased and passing.
Comment #171
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #172
duaelfrRebased on main
Comment #173
larowlanLinking some examples from slack that the PHP fix would break:
* https://github.com/civictheme/uikit/blob/main/packages/twig/components/0...
* https://github.com/previousnext/mxds/blob/main/src/Form/Label/label.twig...
Comment #174
larowlanDiscussed in slack @rikki_iki said:
She makes an excellent point about it being noticeable - so I've changed my mind - let's press ahead with the PHP approach and just note the change in a release note for themers.
Rikki also pointed out we'd need to be able to customise the class.
Comment #178
larowlanLeft a comment about making the required marker markup overidable by a theme per comment from @rikki_iki
Comment #179
kentr commentedThanks @larowlan.
The MR was pretty behind, so I rebased it.
Comment #180
kentr commentedI made it themeable.
Comment #181
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #182
kentr commentedWill rebase
Comment #183
kentr commentedRebased.
Comment #184
rkollerAn early observation, the override stuff i still have to figure out how to manually test first. but to me it looks like
(required)replacing the star does not work for the media field in the latest state of the MR. identical results in safari and edge.Comment #185
kentr commented@rkoller found that the change record still reflects Option 1 and that the new " (required)" text doesn't appear for media fields.
Comment #186
kentr commentedBack to Needs review.
I also checked some other field types that are coded as a "Widget". The media entity reference field seems to be an outlier.
Comment #187
kentr commentedThere's another problem.