Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support of max-width container queries #20

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Nothing yet!
### Added

- Support of `max-width` container queries using `@max` or `atMax` variants.

## [0.1.1] - 2023-03-31

Expand Down
90 changes: 90 additions & 0 deletions README.md
Expand Up @@ -39,6 +39,26 @@ Start by marking an element as a container using the `@container` class, and the

By default we provide [container sizes](#configuration) from `@xs` (`20rem`) to `@7xl` (`80rem`).

In case of `max-width` container queries:

```html
<div class="@container">
<div class="@max-lg:underline">
<!-- This text will be underlined when the container is larger than `32rem` -->
</div>
</div>
```

or alternatively there is an `atMax` version:

```html
<div class="@container">
<div class="atMax-lg:underline">
<!-- This text will be underlined when the container is larger than `32rem` -->
</div>
</div>
```

### Named containers

You can optionally name containers using a `@container/{name}` class, and then include that name in the container variants using classes like `@lg/{name}:underline`:
Expand All @@ -52,6 +72,26 @@ You can optionally name containers using a `@container/{name}` class, and then i
</div>
```

In case of `max-width` container queries:

```html
<div class="@container/main">
<div class="@max-lg/main:underline">
<!-- This text will be underlined when the container is larger than `32rem` -->
</div>
</div>
```

or alternatively the `atMax` version:

```html
<div class="@container/main">
<div class="atMax-lg/main:underline">
<!-- This text will be underlined when the container is larger than `32rem` -->
</div>
</div>
```

### Arbitrary container sizes

In addition to using one of the [container sizes](#configuration) provided by default, you can also create one-off sizes using any arbitrary value:
Expand All @@ -64,6 +104,56 @@ In addition to using one of the [container sizes](#configuration) provided by de
</div>
```

In case of `max-width` container queries:

```html
<div class="@container">
<div class="@max-[17.5rem]:underline">
<!-- This text will be underlined when the container is larger than `32rem` -->
</div>
</div>
```

or alternatively the `atMax` version:

```html
<div class="@container">
<div class="atMax-[17.5rem]:underline">
<!-- This text will be underlined when the container is larger than `32rem` -->
</div>
</div>
```

### Combining named containers and arbitrary container sizes

You can combine both [named containers](#named-containers) and
[arbitrary container sizes](#arbitrary-container-sizes) this way:

```html
<div class="@container/main">
<div class="@[17.5rem]/main:underline"></div>
<!-- This text will be underlined when the container is larger than `17.5rem` -->
</div>
</div>
```

In case of `max-width` container queries only the `atMax` version is working
because to support extraction of `@max-[17.5rem]/main:underline` by the default
extractor of Tailwind CSS its regular expressions would need to be updated
(or a custom extractor could be used but that is really an advanced topic since it
overrides the default one which does really an excellent job to extract class name
candidates from anywhere).

```html
<div class="@container/main">
<div class="atMax-[17.5rem]/main:underline">
<!-- This text will be underlined when the container is larger than `32rem` -->
</div>
</div>
```



### Removing a container

To stop an element from acting as a container, use the `@container-normal` class.
Expand Down
70 changes: 50 additions & 20 deletions src/index.ts
Expand Up @@ -29,6 +29,34 @@ export = plugin(
}
)

const sort: (
a: { value: string; modifier: string | null },
b: { value: string; modifier: string | null }
) => number = (aVariant, zVariant) => {
let a = parseFloat(aVariant.value)
let z = parseFloat(zVariant.value)

if (a === null || z === null) return 0

// Sort values themselves regardless of unit
if (a - z !== 0) return a - z

let aLabel = aVariant.modifier ?? ''
let zLabel = zVariant.modifier ?? ''

// Explicitly move empty labels to the end
if (aLabel === '' && zLabel !== '') {
return 1
} else if (aLabel !== '' && zLabel === '') {
return -1
}

// Sort labels alphabetically in the English locale
// We are intentionally overriding the locale because we do not want the sort to
// be affected by the machine's locale (be it a developer or CI environment)
return aLabel.localeCompare(zLabel, 'en', { numeric: true })
}

matchVariant(
'@',
(value = '', { modifier }) => {
Expand All @@ -38,32 +66,34 @@ export = plugin(
},
{
values,
sort(aVariant, zVariant) {
let a = parseFloat(aVariant.value)
let z = parseFloat(zVariant.value)

if (a === null || z === null) return 0
sort,
}
)

// Sort values themselves regardless of unit
if (a - z !== 0) return a - z
const maxVariantFn: (value: string, { modifier }: { modifier: string | null }) => string | string[] = (value = '', { modifier }) => {
let parsed = parseValue(value)

let aLabel = aVariant.modifier ?? ''
let zLabel = zVariant.modifier ?? ''
return parsed !== null ? `@container ${modifier ?? ''} (max-width: ${value})` : []
}

// Explicitly move empty labels to the end
if (aLabel === '' && zLabel !== '') {
return 1
} else if (aLabel !== '' && zLabel === '') {
return -1
}
matchVariant(
'@max',
maxVariantFn,
{
values,
sort,
}
)

// Sort labels alphabetically in the English locale
// We are intentionally overriding the locale because we do not want the sort to
// be affected by the machine's locale (be it a developer or CI environment)
return aLabel.localeCompare(zLabel, 'en', { numeric: true })
},
matchVariant(
'atMax',
maxVariantFn,
{
values,
sort,
}
)

},
{
theme: {
Expand Down