-
Notifications
You must be signed in to change notification settings - Fork 17
WLabel
WLabel is a component used for adding labels to WComponents which output form controls. It is notionally possible to associate a WLabel with any WComponent but not all components produce labellable elements, therefore WLabel will output the correct HTML element dependent upon the component being labeled.
- Why use WLabel
- Creating WLabel
- Input component
- Label content
- Accessibility
- HTML output
- Appearance
- Hiding
- Long labels
- Testing
- Related components
- Further information
WLabel allows WComponents which output form controls to be labelled in an appropriate way irrespective of the output of the component. If a WLabel is applied to any other WComponent it will still output an appropriate HTML element.
It is a fundamental requirement that all form controls should be appropriately labelled to meet WCAG Success Criterion 3.3.2. It could even be argued that this is the first port of call for accessibility and the simplest to implement. It is staggering how often this is not done. WLabel, especially in conjunction with WFieldLayout, makes it easier to meet basic accessibility requirements.
If an interface contains any WComponent which outputs one or more form controls then you probably need WLabel. There are some times WLabel may be omitted but these should be edge cases. See Unlabelled inputs for more information about when form controls may be present without using WLabel.
WLabel may be instantiated directly by calling a constructor or implicitly through WFieldLayout.addField(String, WComponent). The default constructor creates an empty WLabel which is not associated with any form control. Constructors which accept a WComponent argument will associate the WLabel with that WComponent.
// create a WLabel with text content
WLabel label = new WLabel("Name");
// Create a WLabel 'for' another component
WTextField txtNameField = new WTextField();
WLabel lblNameField = new WLabel("Name", txtNameField);
// Create a WLabel implicitly through WFieldLayout.addField
// Given WFieldLayout layout...
layout.addField("Name", new WTextField());
// or with an input component 'input'
layout.addField("Name", input);
// Create a WLabel with a string name and an access key
WLabel label = new WLabel("Name", 'N');
// Create a WLabel with a name and access key
// associated with WCOmponent `input`
WLabel label = new WLabel("Name", 'N', input);
// To get the WLabel from a WField when it has been created implicitly
// Given WField field
WLabel label = field.getLabel();
A WLabel should label an input component. This association may be done during construction or afterwards using setForComponent
.
// Given WComponent `input` and WLabel `label`
// associate the WLabel with the component.
label.setForComponent(input);
The labelled WComponent may be obtained from an instance of WLabel.
// given WLabel `label`
WComponent labelledComponent = label.getLabelFor();
If the labelled input has constraints (such as a maximum date on a WDateField) a readable description of these constraints should be included in the label content. A common place for these constraints is in the label hint.
// Given a WDateField dobField which must contain a date
WLabel dobLabel = new WLabel("Date of birth", dobField);
dobLabel.setHint("Date must be no later than today");
The content of a WLabel must be palpable and accessible to all users. It is strongly recommended that the content of a WLabel is a string. A WLabel may contain non-text content so long as that content has a text equivalent which adequately labels the corresponding form control. For example a label for a credit card selection WRadioButton may contain an image corresponding to the branding of the credit card but that image must have alt text which indicates the type of credit card option being represented.
WLabel supports unescaped content. This means it is possible to have raw HTML in a WLabel. This is best avoided, for example the following option for creating a coloured label is usually a very bad idea:
WHeading unescapedLabel = new WLabel(
"<span style='color:red'>Red label (unescaped text)</span>",
someInput);
unescapedLabel.setEncodeText(false);
If a label contains punctuation unescaped content may be appropriate:
WHeading unescapedLabel = new WLabel("Spouse‘s Name",
nameField);
// if not unescaped would output "Spouse"s Name"
unescapedLabel.setEncodeText(false);
// will now output "Spouse’s Name"
The content of a WLabel may be sanitized on output if it contains unescaped text. This will limit the output to 'safe' text and markup. This sanitization is not done by default as most WLabels should contain escaped content or at the very least content which is in the control of the application. If the WLabel contains unescaped text which is drawn from any external source (such as a database) then it should be sanitized.
// With WLabel `label`
label.setSanitizeOnOutput(true);
A hint is an optional text property of WLabel which can be used to provide extra content to the label which is output as a part of the label but in a different style. It is used to provide extra contextual information to a label.
It is recommended that the WLabel hint be used if the labelled component has input constraints. If a WDateField, for example, must contain a date within a specified range then the conditions should be indicated, in a human readable form, in the WLabel hint.
// Given a WDateField dobField which must contain a date
// on or before 'today'
WLabel dobLabel = new WLabel("Date of birth", dobField);
dobLabel.setHint("Date must be no later than today");
Firstly: it is best is a WLabel contains only text and that text adequately describes the purpose of the labelled control. The following describes scenarios when WLabel does not contain only text: all of these scenarios are sub-optimal.
WLabel may (but probably shouldn't) contain any other component which outputs phrasing content except another WLabel and with a limit of no more than one labellable element and no button controls.
It is strongly recommended that WLabel does not contain any form components, however a WLabel may contain exactly one simple form control (except button controls) but the WLabel must be for
that form component.
Recommended content for WLabel:
- Text;
- WAbbrText;
-
WStyledText with no
white-space
setting; - WDecoratedLabel with only phrasing content;
- WImage;
- WContainer containing any combination of the above.
WLabel is primarily concerned with accessible labelling of other WComponents but must itself be accessible. The output of a WLabel will vary according to the component being labelled.
Labels should be succinct. They must provide enough information to indicate the purpose of the labelled control but should not be convoluted. See [long labels below] for more information about long label content and placement.
If a WLabel is for a WComponent which outputs a labelable element (other than a button component) then its position ought be as per G162: Positioning labels to maximize predictability of relationships. A quick description of the application of this technique is:
- if the WLabel is for a WCheckBox or WRadioButton then the WLabel must immediately follow the labelled WComponent;
- in all other cases the WLabel must closely precede the labelled WComponent with no intermediate perceptible content.
WComponents which output complex form controls should be associated with a WLabel. The WLabel transforms to a span and a legend element. Only one or other of these will be visible on screen at any given time. This will, in the default theme, be the legend unless the label:input pair is in a WFieldLayout with LAYOUT_FLAT
.
Using WFieldLayout and WField to add label:component pairs to a UI will ensure all of these requirements are met and that the appearance of label:component pairs is consistent across the various categories of elements output from the WComponents. The best way to ensure consistent layout a label relative to its labelled component is to use the layout property of WFieldLayout.
If a label has particularly long content (rewrite it) then it may be more difficult to place. Some techniques for addressing this are described below.
WLabel may be given an access key to the target component of the WLabel (where possible). The use of access keys is controversial and may increase and decrease accessibility depending on how they are used. See Using access keys for more information.
// given WLabel `label`
label.setAccessKey('M');
Mandatory fields are indicated in WComponents in the following way:
- if the HTML element output by the component supports the supports the
required
attribute then that attribute is applied to the mandatory component; otherwise the component itself is marked as mandatory by having the WAI-ARIA statearia-required="true"
; and - the label for a mandatory field is styled to have a required marker.
This mechanism does not have to include extra information for users of assistive technologies due to the required
/aria-required
setting described above. The label indicator is a secondary indicator of the mandatory state of the control. The indication that a field is mandatory is a facet of the WComponent which outputs the field, not upon the WLabel for the WComponent.
If an application requires a key to indicate the intent of the mandatory indicator then WStyledText may be used and is guaranteed to have the same appearance as a WLabel for a mandatory field.
WLabel may have a toolTip. This information may not be available to keyboard-only users who do not use display assistive technologies and therefore should not contain information vital to the purpose of the label.
It is strongly recommended that this property is never used on a WLabel. If extra information is required in a WLabel it may be more appropriate to use a hint.
The HTML output of WLabel is dependent upon the WComponent being labeled and us shown in the table below. In all cases the element has a content model of phrasing-content and therefore must not contain any Components which output non-phrasing content.
WComponent | HTML output | Notes |
---|---|---|
Any WComponent in a read-only state | span | This element will have no label-like behaviour |
WButton | span | Should not be labelled |
WPrintButton | span | Should not be labelled |
WComponents which output labelable elements which are not buttons | label | |
WComponents which output complex form controls | legend and span | |
Other WComponents and WLabels which are not "for" any WComponent | span | Should not be labelled |
Notes
The images below show samples using the default wcomponents-theme. The actual label appearance will depend on the theme in use.
- A sample WLabel 'for' a WTextField:
- A sample WLabel 'for' a WCheckBoxSelect:
In this example the check boxes are in a fieldset and the WLabel generates the legend which is rendered outside of the viewport. The visible 'label' is has attributearia-hidden="true"
so that AT do not read the content twice as the real labelling component is the legend. - A sample label 'for' a WCheckBox:
When a WLabel is 'for' a WCheckBox or WRadioButton it must immediately follow the labelled control. When usingWFieldLayout.addField
to add label/input pairs WComponents will ensure each type of form control has its label in the correct place. - A sample showing a hidden WLabel:
In this example the second WTextField is associated with a WLabel which is hidden.
WLabel may have one or more values to be added to the component's root element. This can be used for fine-grain styling of specific components but should be used with care. It is not recommended this facility be used with labels as it may result in a reduction in application usability and/or accessibility.
For more information see WComponents HTML class property.
A WLabel may be hidden on page load. When hidden the WLabel is moved out of the viewport but is still available to assistive technologies, this could be used, for example, for multiple text fields in an address block. This differs from the hidden state of other WComponents which hides the component from all conforming user agents. In addition, if the component labeled by the WLabel is hidden then the WLabel will also be hidden. In this case the WLabel will be hidden from all conforming user agents including assistive technologies. Showing a component using WSubordinateControl will also show its label, which may be rendered outside of the viewport depending upon the WLabel's own hidden setting.
// Assume a WTextField used to gather an optional second address line
WLabel secondAddressLineLabel = new WLabel("Street address line two");
// Do not show the label in the UI
secondAddressLineLabel.setHidden(true);
NOTE: In some cases it may be more appropriate to use the labelled component's toolTip or accessibleText property rather than creating a hidden WLabel.
Despite best efforts at copy writing sometimes a form control will have a long label. Long label text is an accessibility problem but not one which WComponents is able to address directly. The only accessible way to use a long label is to rewrite it as a short label. Given that one will occasionally have to design a UI with one or more excessively long labels there are a few options for dealing with them.
This is probably the best way to deal with a long label as it allows the label to flow across the available space and therefore occupy fewer vertical lines. This must be weighed against the reduced readability of excessive line length though, so you must be aware of the total line length when the label is presented.
To position a label above a control the label:control pair are added to a WFieldLayout with its layout property set to STACKED
.
The default arrangement for a STACKED WFieldLayout is to place the controls inline with the left edge of the labels. This may cause issues with UI consistency if the rest of the form controls are in a FLAT WFieldLayout. To address this a STACKED WFieldLayout may have its labelWidth property set to the same value as surrounding FLAT WFieldLayout(s) and this will result in the controls being indented to the same degree. NOTE: setting the labelWidth property does not affect the width available to the label in a STACKED layout.
In some cases the absolute line length of a label above a control may be so long as to outweigh the readability advantages over a multi-line wrapped block. In these cases it may be better to place the label alongside the control (if other label:control pairs are so arranged). In this case it may be better to use the hint property to hold some of the label content.
A hint can be used to add extended information to a label. This is then displayed as part of the label and usually in a different style (often slightly smaller or lighter in weight) from the core part of the label. This allows the core information needed in the label to stand out which may allow the user to concentrate on that core information.
The label hint:
- will not reduce the word length of the label and may even result in the label occupying more vertical space;
- does not help address most accessibility issues surrounding long labels;
- does help improve the usability of a long label, to a small extent, by splitting the label into differently styled core part and additional information.
The split between the core label and the hint is stylistic not semantic, the hint is still part of the label and carries no structural information or extended accessibility helpers.
WLabel is accessible to Selenium tests using the com.github.bordertech.wcomponents.test.selenium.element.SeleniumWLabelWebElement
extension of org.openqa.selenium.WebElement
. This WebElement
extension provides the following helpers:
-
WebElement getHint()
will get the HTML element which contains the hint (if any). -
SeleniumWComponentWebElement getLabelledComponent()
wil get the WComponent the label isfor
though it should be noted that if the purpose of getting the label was only to get to the labelled component then it is better to usecom.github.bordertech.wcomponents.test.selenium.ByLabel
and get the component's WebElement directly, especially as this By extension may be used in conjunction with SeleniumWComponentsWebDriver to acquire specific extensions of SeleniumWComponentWebElement. -
boolean isHidden()
tests for WLabel's special inplementation of the hidden state. -
boolean isReadOnly()
returnstrue
if the WLabel isfor
an Input in a read-only state.
SeleniumWLabelWebElement extends SeleniumWComponentWebElement so also implements its methods.
- WComponent form controls
- Labelable WComponents
- WDecoratedLabel is used as a labelling component of some containers and non-labellable interactive controls
- Unlabelled inputs;
- JavaDoc;
- HTML Specification;
- Labels or Instructions: Understanding SC 3.3.2
- G131: Providing descriptive labels
- H44: Using label elements to associate text labels with form controls
- H65: Using the title attribute to identify form controls when the label element cannot be used
- G162: Positioning labels to maximize predictability of relationships
- List of WComponents.