Media Query Modifiers API ReferenceType-safe media query support for responsive design in the Summon framework. Provides declarative helpers for applying styles based on viewport dimensions, device characteristics, and user preferences.
☰Navigation

Media Query Modifiers API Reference

Overview

Type-safe media query support for responsive design in the Summon framework. Provides declarative helpers for applying styles based on viewport dimensions, device characteristics, and user preferences.

Package: codes.yousef.summon.modifier
Since: 0.4.8.4

MediaQuery Types

All media query types extend the sealed class MediaQuery:

sealed class MediaQuery {
    abstract override fun toString(): String
}

Viewport Queries

MinWidth

Applies styles when viewport width is at least the specified value.

data class MinWidth(val pixels: Int) : MediaQuery()

Example:

MediaQuery.MinWidth(768) // (min-width: 768px)

MaxWidth

Applies styles when viewport width is at most the specified value.

data class MaxWidth(val pixels: Int) : MediaQuery()

Example:

MediaQuery.MaxWidth(1024) // (max-width: 1024px)

MinHeight

Applies styles when viewport height is at least the specified value.

data class MinHeight(val pixels: Int) : MediaQuery()

Example:

MediaQuery.MinHeight(600) // (min-height: 600px)

MaxHeight

Applies styles when viewport height is at most the specified value.

data class MaxHeight(val pixels: Int) : MediaQuery()

Example:

MediaQuery.MaxHeight(900) // (max-height: 900px)

Orientation Queries

Portrait

Applies styles when device is in portrait mode (height >= width).

object Portrait : MediaQuery()

Example:

MediaQuery.Portrait // (orientation: portrait)

Landscape

Applies styles when device is in landscape mode (width > height).

object Landscape : MediaQuery()

Example:

MediaQuery.Landscape // (orientation: landscape)

User Preference Queries

PrefersDarkScheme

Applies styles when user prefers dark color scheme.

object PrefersDarkScheme : MediaQuery()

Example:

MediaQuery.PrefersDarkScheme // (prefers-color-scheme: dark)

PrefersLightScheme

Applies styles when user prefers light color scheme.

object PrefersLightScheme : MediaQuery()

Example:

MediaQuery.PrefersLightScheme // (prefers-color-scheme: light)

PrefersReducedMotion

Applies styles when user prefers reduced motion.

object PrefersReducedMotion : MediaQuery()

Example:

MediaQuery.PrefersReducedMotion // (prefers-reduced-motion: reduce)

Device Capability Queries

CanHover

Applies styles on devices that support hover (typically desktops).

object CanHover : MediaQuery()

Example:

MediaQuery.CanHover // (hover: hover)

NoHover

Applies styles on devices without hover support (typically touch devices).

object NoHover : MediaQuery()

Example:

MediaQuery.NoHover // (hover: none)

FinePointer

Applies styles on devices with precise pointer input (mouse).

object FinePointer : MediaQuery()

Example:

MediaQuery.FinePointer // (pointer: fine)

CoarsePointer

Applies styles on devices with imprecise pointer input (touch screens).

object CoarsePointer : MediaQuery()

Example:

MediaQuery.CoarsePointer // (pointer: coarse)

Logical Operators

And

Combines multiple queries with AND logic (all must be true).

data class And(val queries: List<MediaQuery>) : MediaQuery() {
    constructor(vararg queries: MediaQuery) : this(queries.toList())
}

Example:

MediaQuery.And(
    MediaQuery.MinWidth(768),
    MediaQuery.Portrait
)
// (min-width: 768px) and (orientation: portrait)

Or

Combines multiple queries with OR logic (at least one must be true).

data class Or(val queries: List<MediaQuery>) : MediaQuery() {
    constructor(vararg queries: MediaQuery) : this(queries.toList())
}

Example:

MediaQuery.Or(
    MediaQuery.MinWidth(1024),
    MediaQuery.Landscape
)
// (min-width: 1024px), (orientation: landscape)

Custom

Custom media query for advanced use cases.

data class Custom(val query: String) : MediaQuery()

Example:

MediaQuery.Custom("(aspect-ratio: 16/9)")

Modifier Functions

mediaQuery

Applies styles conditionally based on a media query.

Signature:

fun Modifier.mediaQuery(
    query: MediaQuery,
    builder: Modifier.() -> Modifier
): Modifier

Parameters:

  • query: MediaQuery - The media query condition
  • builder: Modifier.() -> Modifier - DSL builder for styles to apply when query matches

Returns: A new Modifier with media query styles

Example:

Box(modifier = Modifier()
    .padding("8px")
    .mediaQuery(MediaQuery.MinWidth(768)) {
        padding("16px")
    }
    .mediaQuery(MediaQuery.MinWidth(1024)) {
        padding("24px")
    }
)

Breakpoints Object

Predefined breakpoint constants for common screen sizes.

object Breakpoints {
    /** Small mobile devices (320px) */
    val XS = 320
    
    /** Mobile devices (640px) */
    val SM = 640
    
    /** Tablets (768px) */
    val MD = 768
    
    /** Small desktops (1024px) */
    val LG = 1024
    
    /** Large desktops (1280px) */
    val XL = 1280
    
    /** Extra large screens (1536px) */
    val XXL = 1536
}

Usage:

Box(modifier = Modifier()
    .fontSize("14px")
    .mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) {
        fontSize("16px")
    }
    .mediaQuery(MediaQuery.MinWidth(Breakpoints.LG)) {
        fontSize("18px")
    }
)

Usage Examples

Responsive Padding

Box(modifier = Modifier()
    .padding("8px")  // Mobile
    .mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) {
        padding("16px")  // Tablet
    }
    .mediaQuery(MediaQuery.MinWidth(Breakpoints.LG)) {
        padding("24px")  // Desktop
    }
)

Dark Mode Support

Box(modifier = Modifier()
    .backgroundColor("#ffffff")
    .color("#000000")
    .mediaQuery(MediaQuery.PrefersDarkScheme) {
        backgroundColor("#1a1a1a")
        color("#ffffff")
    }
)

Reduced Motion Support

Box(modifier = Modifier()
    .transition("all", duration = 300)
    .mediaQuery(MediaQuery.PrefersReducedMotion) {
        transition("none")
    }
)

Device-Specific Styles

Button(
    modifier = Modifier()
        .padding("8px 16px")
        .mediaQuery(MediaQuery.NoHover) {
            padding("12px 20px")  // Larger touch target
        }
        .mediaQuery(MediaQuery.CanHover) {
            cursor("pointer")
        }
)

Complex Queries

Box(modifier = Modifier()
    .width("100%")
    .mediaQuery(
        MediaQuery.And(
            MediaQuery.MinWidth(768),
            MediaQuery.Landscape
        )
    ) {
        width("50%")
    }
)

Mobile-First Approach

// Start with mobile styles, enhance for larger screens
Box(modifier = Modifier()
    .fontSize("14px")
    .lineHeight("1.5")
    .padding("16px")
    // Tablet
    .mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) {
        fontSize("16px")
        padding("24px")
    }
    // Desktop
    .mediaQuery(MediaQuery.MinWidth(Breakpoints.LG)) {
        fontSize("18px")
        lineHeight("1.6")
        padding("32px")
    }
)

Desktop-First Approach

// Start with desktop styles, override for smaller screens
Box(modifier = Modifier()
    .fontSize("18px")
    .padding("32px")
    // Tablet
    .mediaQuery(MediaQuery.MaxWidth(Breakpoints.LG)) {
        fontSize("16px")
        padding("24px")
    }
    // Mobile
    .mediaQuery(MediaQuery.MaxWidth(Breakpoints.MD)) {
        fontSize("14px")
        padding("16px")
    }
)

Implementation Details

How It Works

  1. Media query styles are stored as data attributes
  2. Platform renderer detects these attributes
  3. StyleInjector generates @media rules with unique class names
  4. CSS is injected into document <head>
  5. Elements automatically get the generated class

Generated CSS Example

// This code:
Box(modifier = Modifier()
    .padding("8px")
    .mediaQuery(MediaQuery.MinWidth(768)) {
        padding("16px")
    }
)

// Generates CSS like:
@media (min-width: 768px) {
  .media-abc123 {
    padding: 16px;
  }
}

Best Practices

1. Choose an Approach

// Mobile-first (recommended)
Modifier()
    .fontSize("14px")
    .mediaQuery(MediaQuery.MinWidth(768)) { fontSize("16px") }

// Desktop-first
Modifier()
    .fontSize("18px")
    .mediaQuery(MediaQuery.MaxWidth(768)) { fontSize("14px") }

2. Use Predefined Breakpoints

// Good
.mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) { }

// Avoid magic numbers
.mediaQuery(MediaQuery.MinWidth(768)) { }
// Good
.mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) {
    padding("16px")
    fontSize("16px")
    lineHeight("1.6")
}

// Avoid
.mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) { padding("16px") }
.mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) { fontSize("16px") }
.mediaQuery(MediaQuery.MinWidth(Breakpoints.MD)) { lineHeight("1.6") }

4. Consider User Preferences

// Always provide fallbacks for dark mode
.backgroundColor("#ffffff")
.mediaQuery(MediaQuery.PrefersDarkScheme) {
    backgroundColor("#1a1a1a")
}

// Respect reduced motion
.transition("all", 300)
.mediaQuery(MediaQuery.PrefersReducedMotion) {
    transition("none")
}

Performance Considerations

Efficient Media Queries

  • Use standard breakpoints to maximize style reuse
  • Avoid excessive unique media queries
  • Group related styles together

CSS Generation

  • Styles are cached and reused
  • Duplicate media queries share the same @media rule
  • Automatic cleanup prevents memory leaks

Browser Support

Query TypeSupport
Width/HeightAll modern browsers
OrientationAll modern browsers
Dark/Light SchemeChrome 76+, Safari 12.1+, Firefox 67+
Reduced MotionChrome 74+, Safari 10.1+, Firefox 63+
HoverChrome 38+, Safari 9+, Firefox 64+
PointerChrome 41+, Safari 9+, Firefox 64+

See Also

Architected in Kotlin. Rendered with Materia. Powered by Aether.
© 2026 Yousef.