Skip to content

Commit

Permalink
feat(SASS mixins): media queries mixins now uses 0.1px instead of 1px…
Browse files Browse the repository at this point in the history
… to avoid overlap (#3985)

The `1px` overlap-avoidance between media queries created a `0.999...px`
gap between mixin media queries. That is visible if user zooms in. This
PR changes that to `0.1px` so you would have to zoom in more than 1000%
in order to get a gap.

### Example: browser with 200% zoom and 640.5px with 
1. `'small'` breakpoint `40em = 640px
3. `allBelow('small')` `0px to 640px` is narrower than `640.5px`
4. `allAbove('small')` `641px to infinity` is wider than `640.5px`
5. Changing `allAbove('small')` to `640.1px to infinity` includes
`640.5px`

### Changes:
* changed overlap-avoidance from `1px` to `0.1px` in both SASS mixins
and react hooks.
* updated documentation for "SASS and Mixins" and "Media Queries and
Breakpints" to make it clearer that we do not include the minimum
breakpoint in our intervals.

### other fixes:
* fixed Portal Home button breakpoint off by 1 px
* fixed a bug where you could not use any other unit than `em` for
`allAbove` and `allBetween` mixin.
* fixed a bug where `$breakpoint-offset`. was not used in `allBetween`
mixin.
* fixed a bug with parsing `'and'` in array sizes for
`MediaQueryUtils.ts`
* added a comment that `handheld` is a
[deprecated](https://developer.mozilla.org/en-US/docs/Web/CSS/@media#sect2)
media-type in 'MediaQueryUtils.ts' (should we remove it?)

---------

Co-authored-by: Tobias Høegh <tobias@tujo.no>
  • Loading branch information
snorrekim and tujoworker authored Sep 24, 2024
1 parent c945d5b commit 1cb495a
Show file tree
Hide file tree
Showing 23 changed files with 122 additions and 74 deletions.
11 changes: 11 additions & 0 deletions packages/dnb-design-system-portal/src/docs/uilib/helpers/sass.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,27 @@ You can import Eufemia _mixins_ directly into your SCSS styles:

Use the `allAbove`, `allBelow` and `allBetween` mixins to add media queries to your css.

To prevent overlapping media queries, `0.00625em` gets added to the minimum width. This results in an increment of approximately `0.1px` when using `em` units. If you're using a unit other than `em`, you may need to adjust this value accordingly, as `0.00625px` is typically too small to effectively prevent overlaps.

| mixin | actual interval (em) | actual interval (px) |
| ----------------------- | ---------------------- | -------------------- |
| `allBelow(40em)` | 0 to 40em | 0 to 640px |
| `allBetween(40em,60em)` | 40.00625em to 60em | 640.1px to 960px |
| `allAbove(60em)` | 60.00625em to infinity | 960.1px to infinity |

```scss
@import '@dnb/eufemia/style/core/utilities.scss';

@include allBelow(small) {
// from 0px to 'small' (640px)
}

@include allBetween(small, medium) {
// from 640.1px ('small' + 0.1px) to 960px ('medium')
}

@include allAbove(medium) {
// from 960.1px ('medium' + 0.1px) and wider
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ UX designers are using a 12 column system during their design processes.

Application in DNB do actually break only twice (`small` and `medium`). But have a HTML body max-width of `large`.

| Name | Range | Mixin | Columns |
| ---------- | ----------------- | --------------------------- | ------- |
| `isSmall` | from 0 to 40em | `allBelow(small)` | 4 |
| `isMedium` | from 40em to 60em | `allBetween(small, medium)` | 6 |
| `isLarge` | from 60em | `allAbove(medium)` | 12 |
| React hook | Range | SASS mixin | Columns |
| ---------- | --------------------------------- | --------------------------- | ------- |
| `isSmall` | from 0 to 40em | `allBelow(small)` | 4 |
| `isMedium` | from (not including) 40em to 60em | `allBetween(small, medium)` | 6 |
| `isLarge` | from (not including) 60em | `allAbove(medium)` | 12 |

<br />
Note: if you've set [custom sass breakpoints](/uilib/helpers/sass/#custom-offset) using `$breakpoints` or `$breakpoint-offset`, the sass mixins will be different.

So when dealing with naming of breakpoint ranges (between breakpoints), we actually use the term "large" when a media query exceeds `medium`:

Expand All @@ -53,8 +53,8 @@ So when dealing with naming of breakpoint ranges (between breakpoints), we actua
Here is how ranges breaks down in pixels:

- The small range goes from 0 to 640px
- The medium range goes from 641px to 960px
- The large range goes from 961px to infinity
- The medium range goes from 640.1px to 960px
- The large range goes from 960.1px to infinity

### UX Design and Breakpoints

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
display: none;
}
}
@include allAbove(small, math.div(1, 16)) {
@include allAbove(small) {
#toggle-main-menu-small-screen {
display: none;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ p > .dnb-icon {
position: static;
max-width: 60rem;
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-accordion-group--single-container .dnb-accordion__header {
width: 40%;
}
Expand All @@ -240,15 +240,15 @@ p > .dnb-icon {
margin-top: 0;
}
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-accordion-group--single-container .dnb-accordion > .dnb-accordion__header .dnb-accordion__header__icon {
transform: rotate(-90deg);
}
}
.dnb-accordion-group--single-container .dnb-accordion-group__children {
max-width: 60rem;
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-accordion-group--single-container .dnb-accordion-group__children {
position: relative;
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2241,7 +2241,7 @@ html:not([data-whatintent=touch]) .dnb-dropdown__status--error:not(.dnb-dropdown
border-radius: 50%;
}
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-dropdown--action-menu .dnb-dropdown__shell .dnb-dropdown__text {
padding: 0 0.5rem;
}
Expand Down Expand Up @@ -2764,7 +2764,7 @@ html[data-visual-test] .dnb-autocomplete .dnb-input__submit-button__button .dnb-
z-index: 3;
cursor: text;
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-autocomplete .dnb-input--has-inner-element .dnb-input__placeholder, .dnb-autocomplete .dnb-input--has-inner-element .dnb-input__input {
padding-right: 0 !important;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ button.dnb-button::-moz-focus-inner {
);
}
}
@media screen and (max-width: 60em) and (min-width: 40.0625em) {
@media screen and (max-width: 60em) and (min-width: 40.00625em) {
.dnb-section {
--breakout: var(--breakout--medium, var(--breakout--fallback));
--background-color--value: var(--background-color--medium);
Expand All @@ -650,7 +650,7 @@ button.dnb-button::-moz-focus-inner {
);
}
}
@media screen and (min-width: 60.0625em) {
@media screen and (min-width: 60.00625em) {
.dnb-section {
--breakout: var(--breakout--large, var(--breakout--fallback));
--background-color--value: var(--background-color--large);
Expand Down Expand Up @@ -791,7 +791,7 @@ html[data-visual-test] .dnb-breadcrumb__multiple .dnb-breadcrumb__item {
display: none;
}
}
@media screen and (min-width: 60.0625em) {
@media screen and (min-width: 60.00625em) {
.dnb-breadcrumb--variant-responsive .dnb-breadcrumb__toggle {
display: none;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3650,7 +3650,7 @@ button .dnb-form-status__text {
.dnb-toggle-button-group__suffix {
font-size: var(--font-size-basis);
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-form-label + .dnb-toggle-button {
transform: translateY(-0.5rem);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ html[data-visual-test] .dnb-modal__overlay, .dnb-modal__overlay--no-animation {
.dnb-drawer--spacing .dnb-drawer__content {
padding: 0 var(--drawer-spacing);
}
@media screen and (min-width: 80.0625em) {
@media screen and (min-width: 80.00625em) {
.dnb-drawer--spacing .dnb-drawer__content {
padding: 0 calc(var(--drawer-spacing) * 1.75);
}
Expand Down Expand Up @@ -1054,7 +1054,7 @@ html:not([data-visual-test]) .dnb-drawer--hide.dnb-drawer--bottom {
.dnb-drawer--spacing .dnb-drawer__header {
padding: 0 var(--drawer-spacing);
}
@media screen and (min-width: 80.0625em) {
@media screen and (min-width: 80.00625em) {
.dnb-drawer--spacing .dnb-drawer__header {
padding: 0 calc(var(--drawer-spacing) * 1.75);
}
Expand Down Expand Up @@ -1094,7 +1094,7 @@ html:not([data-visual-test]) .dnb-drawer--hide.dnb-drawer--bottom {
margin: var(--drawer-spacing) 0;
padding: 0 var(--drawer-spacing);
}
@media screen and (min-width: 80.0625em) {
@media screen and (min-width: 80.00625em) {
.dnb-drawer--spacing .dnb-drawer__navigation.dnb-section {
padding: 0 calc(var(--drawer-spacing) * 1.75);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@ html:not([data-whatintent=touch]) .dnb-dropdown__status--error:not(.dnb-dropdown
border-radius: 50%;
}
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-dropdown--action-menu .dnb-dropdown__shell .dnb-dropdown__text {
padding: 0 0.5rem;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ exports[`FormRow scss has to match style dependencies css 1`] = `
margin-top: 1rem;
}
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-form-row--centered.dnb-form-row:not(.dnb-form-row--vertical) .dnb-form-row__content {
align-items: center;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ button.dnb-button::-moz-focus-inner {
);
}
}
@media screen and (max-width: 60em) and (min-width: 40.0625em) {
@media screen and (max-width: 60em) and (min-width: 40.00625em) {
.dnb-section {
--breakout: var(--breakout--medium, var(--breakout--fallback));
--background-color--value: var(--background-color--medium);
Expand All @@ -650,7 +650,7 @@ button.dnb-button::-moz-focus-inner {
);
}
}
@media screen and (min-width: 60.0625em) {
@media screen and (min-width: 60.00625em) {
.dnb-section {
--breakout: var(--breakout--large, var(--breakout--fallback));
--background-color--value: var(--background-color--large);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ exports[`Section scss has to match style dependencies css 1`] = `
);
}
}
@media screen and (max-width: 60em) and (min-width: 40.0625em) {
@media screen and (max-width: 60em) and (min-width: 40.00625em) {
.dnb-section {
--breakout: var(--breakout--medium, var(--breakout--fallback));
--background-color--value: var(--background-color--medium);
Expand All @@ -87,7 +87,7 @@ exports[`Section scss has to match style dependencies css 1`] = `
);
}
}
@media screen and (min-width: 60.0625em) {
@media screen and (min-width: 60.00625em) {
.dnb-section {
--breakout: var(--breakout--large, var(--breakout--fallback));
--background-color--value: var(--background-color--large);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ button.dnb-button::-moz-focus-inner {
);
}
}
@media screen and (max-width: 60em) and (min-width: 40.0625em) {
@media screen and (max-width: 60em) and (min-width: 40.00625em) {
.dnb-section {
--breakout: var(--breakout--medium, var(--breakout--fallback));
--background-color--value: var(--background-color--medium);
Expand All @@ -650,7 +650,7 @@ button.dnb-button::-moz-focus-inner {
);
}
}
@media screen and (min-width: 60.0625em) {
@media screen and (min-width: 60.00625em) {
.dnb-section {
--breakout: var(--breakout--large, var(--breakout--fallback));
--background-color--value: var(--background-color--large);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,15 +591,15 @@ exports[`Space scss has to match style dependencies css 1`] = `
--padding-bottom: var(--space-b-s);
}
}
@media screen and (max-width: 60em) and (min-width: 40.0625em) {
@media screen and (max-width: 60em) and (min-width: 40.00625em) {
.dnb-space {
--padding-right: var(--space-r-m);
--padding-left: var(--space-l-m);
--padding-top: var(--space-t-m);
--padding-bottom: var(--space-b-m);
}
}
@media screen and (min-width: 60.0625em) {
@media screen and (min-width: 60.00625em) {
.dnb-space {
--padding-right: var(--space-r-l);
--padding-left: var(--space-l-l);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1771,7 +1771,7 @@ button .dnb-form-status__text {
.dnb-toggle-button-group__suffix {
font-size: var(--font-size-basis);
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-form-label + .dnb-toggle-button {
transform: translateY(-0.5rem);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ html[data-visual-test] .dnb-drawer-list--scroll .dnb-drawer-list__options, .dnb-
word-break: break-word;
font-size: inherit;
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-drawer-list__option__suffix {
grid-column: 2;
grid-row: 1/-1;
Expand Down Expand Up @@ -322,7 +322,7 @@ html[data-visual-test] .dnb-drawer-list:not(.dnb-drawer-list--opened) .dnb-drawe
justify-content: flex-start;
align-items: center;
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-drawer-list--action-menu.dnb-drawer-list--is-popup.dnb-drawer-list--left .dnb-drawer-list__list {
left: 0;
}
Expand Down Expand Up @@ -528,7 +528,7 @@ html:not([data-whatintent=touch]) .dnb-drawer-list__option--selected .dnb-drawer
.dnb-drawer-list__option--selected .dnb-drawer-list__option__inner::before {
visibility: hidden;
}
@media screen and (min-width: 40.0625em) {
@media screen and (min-width: 40.00625em) {
.dnb-drawer-list__option--selected .dnb-drawer-list__option__suffix {
z-index: 2;
background-color: inherit;
Expand Down
34 changes: 17 additions & 17 deletions packages/dnb-eufemia/src/shared/MediaQueryUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export type MediaQueryCondition =
minWidth?: number | string | MediaQuerySizes
maxWidth?: number | string | MediaQuerySizes
orientation?: string
handheld?: boolean
not?: boolean
all?: boolean
monochrome?: boolean
Expand Down Expand Up @@ -196,10 +195,10 @@ export function buildQuery(
listOfQueries = listOfQueries.concat(
combineQueries(when, breakpoints, options)
)
} else if (when && typeof when === 'object') {
const query = convertToMediaQuery(when, breakpoints, options)
if (query) {
listOfQueries.push(query)
} else if (typeof when === 'object') {
const queryItem = convertToMediaQuery(when, breakpoints, options)
if (queryItem) {
listOfQueries.push(queryItem)
}
}

Expand Down Expand Up @@ -249,15 +248,8 @@ function combineQueries(
const query = convertToMediaQuery(when, breakpoints, options)

if (query) {
switch (arr[i - 1]) {
case 'and':
listOfQueries.push('and')
break

case 'or':
default:
listOfQueries.push(', ')
break
if (query !== 'and' && arr[i - 1] !== 'and') {
listOfQueries.push(', ')
}

listOfQueries.push(query)
Expand Down Expand Up @@ -303,9 +295,11 @@ export function convertToMediaQuery(
return query.reduce((acc, q, index) => {
acc += objToMediaQuery(q, breakpoints, options)
if (index < query.length - 1) {
acc += ', '
if (q !== 'and' && query[index + 1] !== 'and') {
acc += ','
}
acc += ' '
}

return acc
}, '') as string
}
Expand All @@ -322,6 +316,9 @@ function objToMediaQuery(
breakpoints: MediaQueryBreakpoints = null,
options?: MediaQueryOptions
): string {
if (typeof obj === 'string') {
return obj
}
let hasNot = false
let query: string | Array<null> = Object.keys(obj).reduce(
(acc, feature) => {
Expand All @@ -332,6 +329,9 @@ function objToMediaQuery(
hasNot = true
return acc
}
if (feature === 'monochrome') {
feature = `(${feature})`
}

if (feature === 'min' || feature === 'max') {
feature = `${feature}-width`
Expand Down Expand Up @@ -370,7 +370,7 @@ function objToMediaQuery(
const size =
parseFloat(query.match(/\(min-width: ([0-9]+)em\)/)[1]) || 0
if (size > 0) {
const correctedSize = (size * 16 + 1) / 16
const correctedSize = (size * 16 + 0.1) / 16 // add 0.1px to the minimum to avoid overlap with and equivalent maximum
query = query.replace(
/(min-width: [0-9]+em)/,
`min-width: ${correctedSize}em`
Expand Down
Loading

0 comments on commit 1cb495a

Please sign in to comment.