And/Or decision points (Conjunctions)
Providing a more visual seperation between two decision points by a visual cue (or) based on user testing. Also provide a connecting conjunction to show two parts are connected (and).
GCWeb implementation plan
- 2021-06 - Engage with TBS to show them this design pattern
- 2021-06 - Provide UX research and analysis to describe how pattern helps usability
- 2021-10 - Review and identify requirement to make this functionality enterprise ready
- 2021-11 - Produce accessibility and usability report on its usage on Canada.ca
- 2022-02 - Have this feature as provisional feature in GCWeb and get TBS to publish guidance on how to use it.
- 2022-05 - updated to focus more on using as list items (with or without headers)
- 2022-09 - updated CSS to allow nested decision points
- 2022-11 - updated CSS to allow no border on always stacked items
- 2023-07 - updated CRA to allow no border on all resolutions when stacked
- 2023-10 - Have this feature as provisional/stable feature in GCWeb and get TBS to publish guidance on how to use it.
Todo and for future consideration
- Review code and governance to balance optimal accessibility and ease of implimentation by users.
Lead: CRA - Christopher Oakes (@christopher-o)
Base configurations
Most screen readers can read CSS text, but it's good to lead with or allude to the fact that the options are either mutually exclusive, or part of the entire concept.
Some options are:
- Adding in a lead in statement to explain there are options that are mutually exclusive (or), or mututally connected (and)
- Creating the and/or using the list (
<ul>
) element - Adding option X of X to all headers
- Adding the word "or" as part of the last statement in each column (except the last column)
Using a simple list (without headers) New
Never stacked (always side-by-side)
- This is content for option A
- This is content for option B
- This is content for part A
- This is content for part B
Always stacked (mobile first, no side-by-side)
- This is content for option A
- This is content for option B
- This is content for part A
- This is content for part B
View code
//Never stacked "or"
<ul class="cnjnctn-type-or cnjnctn-xs">
<li class="cnjnctn-col">
This is content for option A
</li>
<li class="cnjnctn-col">
This is content for option B
</li>
</ul>
//Never stacked "and"
<ul class="cnjnctn-type-and cnjnctn-xs">
<li class="cnjnctn-col">
This is content for part A
</li>
<li class="cnjnctn-col">
This is content for part B
</li>
</li>
</ul>
//Always stacked "or"
<ul class="cnjnctn-type-or">
<li class="cnjnctn-col">
This is content for option A
</li>
<li class="cnjnctn-col">
This is content for option B
</li>
</ul>
//Always stacked "and"
<ul class="cnjnctn-type-and">
<li class="cnjnctn-col">
This is content for part A
</li>
<li class="cnjnctn-col">
This is content for part B
</li>
</li>
</ul>
No border on stacked Updated
This can be used when a bordered design (e.g. zebra striping, panel) has already defined the border of the content. The border will only disappear when the items are stacked.
Note: The stacked left border should not be removed if there is sibling information contained within the existing bordered design that does not relate to the and/or design. There is a risk that it may be unclear when the decision point has started or ended.
Always stacked (mobile first, no side-by-side)
Heading
- This is content for option A
- This is content for option B
Heading
- This is content for part A
- This is content for part B
Stacks on small devices, tablets (768px to 992px) and below, no border when stacked
Heading
- This is content for option A
- This is content for option B
Stacks on medium devices, tablets (992px to 1200px) and below, no border when stacked
Heading
- This is content for part A
- This is content for part B
View code
//Always stacked "or" with no border
<section class="panel panel-default">
<header class="panel-heading">
<h5 class="panel-title">Heading</h5>
</header>
<div class="panel-body">
<ul class="cnjnctn-type-or brdr-0">
<li class="cnjnctn-col">
This is content for option A
</li>
<li class="cnjnctn-col">
This is content for option B
</li>
</ul>
</div>
</section>
//Always stacked "and" with no border
<section class="panel panel-default">
<header class="panel-heading">
<h5 class="panel-title">Heading</h5>
</header>
<div class="panel-body">
<ul class="cnjnctn-type-and brdr-0">
<li class="cnjnctn-col">
This is content for part A
</li>
<li class="cnjnctn-col">
This is content for part B
</li>
</li>
</ul>
</div>
</section>
//Stacks on small devices "or", no border when stacked
<section class="panel panel-default">
<header class="panel-heading">
<h5 class="panel-title">Heading</h5>
</header>
<div class="panel-body">
<ul class="cnjnctn-type-or cnjnctn-md brdr-0">
<li class="cnjnctn-col">This is content for option A </li>
<li class="cnjnctn-col">This is content for option B</li>
</ul>
</div>
</section>
//Stacks on medium devices "and", no border when stacked
<section class="panel panel-default">
<header class="panel-heading">
<h5 class="panel-title">Heading</h5>
</header>
<div class="panel-body">
<ul class="cnjnctn-type-and cnjnctn-lg brdr-0">
<li class="cnjnctn-col">This is content for part A </li>
<li class="cnjnctn-col">This is content for part B</li>
</ul>
</div>
Never stacked (always side-by-side)
Header A: Option 1 of 2
This is content for header A
Header B: Option 2 of 2
This is content for header B
Header A
This is content for header A
Header B
This is content for header B
Always stacked (mobile first, no side-by-side)
Header A: Option 1 of 2
This is content for header A
Header B: Option 2 of 2
This is content for header B
Header A
This is content for header A
Header B
This is content for header B
View code
//Never stacked "or"
<div class="cnjnctn-type-or cnjnctn-xs">
<div class="cnjnctn-col">
<h4 class="text-muted">Header A<span class="wb-inv">: Option 1 of 2</span></h4>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h4 class="text-muted">Header B<span class="wb-inv">: Option 2 of 2</span></h4>
<p>This is content for header B</p>
</div>
</div>
//Never stacked "and"
<div class="cnjnctn-type-and cnjnctn-xs">
<div class="cnjnctn-col">
<h4 class="text-muted">Header A</h4>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h4 class="text-muted">Header B</h4>
<p>This is content for header B</p>
</div>
</div>
//Always stacked "or"
<div class="cnjnctn-type-or">
<div class="cnjnctn-col">
<h4 class="text-muted">Header A<span class="wb-inv">: Option 1 of 2</span></h4>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h4 class="text-muted">Header B<span class="wb-inv">: Option 2 of 2</span></h4>
<p>This is content for header B</p>
</div>
</div>
//Always stacked "and"
<div class="cnjnctn-type-and">
<div class="cnjnctn-col">
<h4 class="text-muted">Header A</h4>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h4 class="text-muted">Header B</h4>
<p>This is content for header B</p>
</div>
</div>
Responsive design
Note: all designs going forward will use the "or" model to simplify the amount of examples.
Stacks on extra small devices, phones (<768px)
Header A: Option 1 of 2
This is content for header A
Header B: Option 2 of 2
This is content for header B
Stacks on small devices, tablets (768px to 992px)
Header A: Option 1 of 2
This is content for header A
Header B: Option 2 of 2
This is content for header B
Stacks on medium devices (992px to 1200px)
Header A: Option 1 of 2
This is content for header A
Header B: Option 2 of 2
This is content for header B
View code
//Stacks on extra small devices, phones
<div class="cnjnctn-type-or cnjnctn-sm">
<div class="cnjnctn-col">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of 2</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of 2</span></h5>
<p>This is content for header B</p>
</div>
</div>
//Stacks on small devices, tablets
<div class="cnjnctn-type-or cnjnctn-md">
<div class="cnjnctn-col">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of 2</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of 2</span></h5>
<p>This is content for header B</p>
</div>
</div>
//Stacks on medium devices
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of 2</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of 2</span></h5>
<p>This is content for header B</p>
</div>
</div>
Use the always stacked design to stack across all resolutions.
Extended configurations
Column count
Three columns (example stacks on small devices)
Header A: Option 1 of 3
This is content for header A
Header B: Option 2 of 3
This is content for header B
Header C: Option 3 of 3
This is content for header C
Four columns (example stacks on medium devices)
Header A: Option 1 of 4
This is content for header A
Header B: Option 2 of 4
This is content for header B
Header C: Option 3 of 4
This is content for header C
Header D: Option 4 of 4
This is content for header D
view code
//Three columns (example stacks on small devices)
<div class="cnjnctn-type-or cnjnctn-md">
<div class="cnjnctn-col">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of 3</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of 3</span></h5>
<p>This is content for header B</p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header C<span class="wb-inv">: Option 3 of 3</span></h5>
<p>This is content for header C</p>
</div>
</div>
//Four columns (example stacks on medium devices)
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of 4</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of 4</span></h5>
<p>This is content for header B</p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header C<span class="wb-inv">: Option 3 of 4</span></h5>
<p>This is content for header C</p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header D<span class="wb-inv">: Option 4 of 4</span></h5>
<p>This is content for header D</p>
</div>
</div>
If you require more than four options (columns), consider the always stacked default design.
Nested conjunctionNew
For instances where one of the decision points may have it's own set of decision points.
An or decision point that stacks on small, nested with an always stacked and decision point
Header A: Option 1 of X
This is content for header A
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Header B.1
This is content for header B.1
Header B.2
This is content for header B.2
View code
//nested decision point example
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-80">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A</p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
<div class="cnjnctn-type-and">
<div class="cnjnctn-col">
<h6 class="text-muted">Header B.1</h6>
<p>This is content for header B.1</p>
</div>
<div class="cnjnctn-col">
<h6 class="text-muted">Header B.2</h6>
<p>This is content for header B.2</p>
</div>
</div>
</div>
</div>
Width of column
To accommodate options that might be lopsided in the amount of text but a need to be visually pleasing, the columns can be set to a percentage of itself to allow larger content to wrap less. The default is 100% (cnjnctn-col
).
Note: The width cannot be adjusted based on different resolutions, best to stack the columns when content becomes difficult to read on smaller devices.
Column set to 90% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 90% of default cnjnctn-col-90
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 80% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 80% of default cnjnctn-col-80
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 75% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 75% of default cnjnctn-col-75
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 70% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 70% of default cnjnctn-col-70
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 60% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 60% of default cnjnctn-col-60
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 50% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 50% of default cnjnctn-col-50
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 40% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 40% of default cnjnctn-col-40
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 30% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 30% of default cnjnctn-col-30
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 25% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 25% of default cnjnctn-col-25
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Column set to 20% of original width (example stacks on medium devices)
Header A: Option 1 of X
This is content for header A (at 20% of default cnjnctn-col-20
)
Header B: Option 2 of X
This is content for header B
Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien.
Code
//90% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-90">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//80% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-80">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//75% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-75">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//70% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-70">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//60% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-60">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//50% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-50">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//40% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-40">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//30% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-30">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//25% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-25">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
//20% of default width
<div class="cnjnctn-type-or cnjnctn-lg">
<div class="cnjnctn-col-20">
<h5 class="text-muted">Header A<span class="wb-inv">: Option 1 of X</span></h5>
<p>This is content for header A </p>
</div>
<div class="cnjnctn-col">
<h5 class="text-muted">Header B<span class="wb-inv">: Option 2 of X</span></h5>
<p>This is content for header B</p>
<p>Nam fermentum cursus sodales. Mauris leo leo, congue et fringilla in, egestas eu sapien. </p>
</div>
</div>
Class name | With of column compared to default (in percentage) |
---|---|
cnjnctn-col |
100% (Default) |
cnjnctn-col-90 |
90% |
cnjnctn-col-80 |
80% |
cnjnctn-col-75 |
75% |
cnjnctn-col-70 |
70% |
cnjnctn-col-60 |
60% |
cnjnctn-col-50 |
50% |
cnjnctn-col-40 |
40% |
cnjnctn-col-30 |
30% |
cnjnctn-col-25 |
25% |
cnjnctn-col-20 |
20% |
Page details
- Date modified: