Media Queries
Overview
Media queries in Styleframe provide a powerful way to create responsive designs with full type safety and auto-complete. You can define breakpoints and create adaptive layouts that work seamlessly across all device sizes while maintaining the benefits of Styleframe's TypeScript support.
Why use media queries?
Media queries help you:
- Create responsive designs: Build layouts that adapt perfectly to different screen sizes and devices.
- Maintain design consistency: Use variables and tokens to ensure consistent spacing and sizing across breakpoints.
- Write maintainable code: Leverage type safety and organized structure to prevent common responsive design mistakes.
- Optimize performance: Generate clean, efficient CSS that loads quickly on all devices.
Defining Media Queries
You define media queries using the media() function from your styleframe instance:
import { styleframe } from 'styleframe';
const s = styleframe();
const { selector, media } = s;
selector('.container', {
width: '100%',
padding: '1rem',
});
media('(min-width: 768px)', ({ selector }) => {
selector('.container', {
width: '750px',
margin: '0 auto',
});
});
media('(min-width: 1024px)', ({ selector }) => {
selector('.container', {
width: '980px',
padding: '2rem',
});
});
export default s;
.container {
width: 100%;
padding: 1rem;
}
@media (min-width: 768px) {
.container {
width: 750px;
margin: 0 auto;
}
}
@media (min-width: 1024px) {
.container {
width: 980px;
padding: 2rem;
}
}
The media() function takes a media query string and a callback function that receives the styleframe context, allowing you to define selectors that will be wrapped in the media query.
Nesting Media Queries
You can nest media queries to create more specific targeting and improve readability:
a. Callback Nesting
For more complex nesting scenarios or when you need to generate media queries dynamically, you can use the callback-based approach.
import { styleframe } from 'styleframe';
const s = styleframe();
const { selector, media } = s;
selector('.container', {
width: '100%',
padding: '1rem',
}, ({ media }) => {
media('(min-width: 768px)', {
width: '750px',
margin: '0 auto',
});
media('(min-width: 1024px)', {
width: '980px',
padding: '2rem',
});
});
export default s;
.container {
width: 100%;
padding: 1rem;
@media (min-width: 768px) {
width: 750px;
margin: 0 auto;
}
@media (min-width: 1024px) {
width: 980px;
padding: 2rem;
}
}
b. Inline Nesting
Alternatively, you can use inline nesting syntax for simpler nested media query definitions:
import { styleframe } from 'styleframe';
const s = styleframe();
const { selector, media } = s;
selector('.container', {
width: '100%',
padding: '1rem',
'@media (min-width: 768px)': {
width: '750px',
margin: '0 auto',
},
'@media (min-width: 1024px)': {
width: '980px',
padding: '2rem',
}
});
export default s;
.container {
width: 100%;
padding: 1rem;
@media (min-width: 768px) {
width: 750px;
margin: 0 auto;
}
@media (min-width: 1024px) {
width: 980px;
padding: 2rem;
}
}
Examples
Breakpoint Variables
For better maintainability, define your breakpoints as variables and use them with the media() function:
import { styleframe, css } from 'styleframe';
const s = styleframe();
const { variable, ref, selector } = s;
const breakpointXs = variable('breakpoint--xs', 0, options);
const breakpointSm = variable('breakpoint--sm', 576, options);
const breakpointMd = variable('breakpoint--md', 992, options);
const breakpointLg = variable('breakpoint--lg', 1200, options);
const breakpointXl = variable('breakpoint--xl', 1440, options);
selector('.responsive-grid', {
display: 'grid',
gridTemplateColumns: '1fr',
gap: '1rem',
}, ({ media }) => {
media(css`(min-width: ${ref(breakpointSm)})`, {
gridTemplateColumns: 'repeat(2, 1fr)',
});
media(css`(min-width: ${ref(breakpointLg)})`,{
gridTemplateColumns: 'repeat(4, 1fr)',
});
});
export default s;
:root {
--breakpoint--xs: 0;
--breakpoint--sm: 576px;
--breakpoint--md: 992px;
--breakpoint--lg: 1200px;
--breakpoint--xl: 1440px;
}
.responsive-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
@media (min-width: 640px) {
grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 1024px) {
grid-template-columns: repeat(4, 1fr);
}
}
Responsive Typography
You can also use media queries to create responsive typography that adapts to different screen sizes:
import { styleframe } from 'styleframe';
const s = styleframe();
const { selector, media } = s;
selector('.responsive-text', {
fontSize: '16px',
lineHeight: '1.5',
});
media('(min-width: 768px)', ({ selector }) => {
selector('.responsive-text', {
fontSize: '18px',
});
});
media('(min-width: 1024px)', ({ selector }) => {
selector('.responsive-text', {
fontSize: '20px',
});
});
export default s;
.responsive-text {
font-size: 16px;
line-height: 1.5;
}
@media (min-width: 768px) {
.responsive-text {
font-size: 18px;
}
}
@media (min-width: 1024px) {
.responsive-text {
font-size: 20px;
}
}
Complex Media Queries
The media() function supports all CSS media query features, including complex conditions:
import { styleframe } from 'styleframe';
const s = styleframe();
const { selector, media } = s;
selector('.adaptive-component', {
padding: '1rem',
backgroundColor: '#f5f5f5',
});
// Tablet landscape
media('(min-width: 768px) and (max-width: 1023px) and (orientation: landscape)', ({ selector }) => {
selector('.adaptive-component', {
padding: '1.5rem',
backgroundColor: '#e5e5e5',
});
});
// High DPI screens
media('(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)', ({ selector }) => {
selector('.adaptive-component', {
backgroundImage: 'url("image@2x.png")',
});
});
// Dark mode preference
media('(prefers-color-scheme: dark)', ({ selector }) => {
selector('.adaptive-component', {
backgroundColor: '#1a1a1a',
color: '#ffffff',
});
});
// Reduced motion preference
media('(prefers-reduced-motion: reduce)', ({ selector }) => {
selector('.adaptive-component', {
transition: 'none',
animation: 'none',
});
});
export default s;
.adaptive-component {
padding: 1rem;
background-color: #f5f5f5;
}
@media (min-width: 768px) and (max-width: 1023px) and (orientation: landscape) {
.adaptive-component {
padding: 1.5rem;
background-color: #e5e5e5;
}
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.adaptive-component {
background-image: url("image@2x.png");
}
}
@media (prefers-color-scheme: dark) {
.adaptive-component {
background-color: #1a1a1a;
color: #ffffff;
}
}
@media (prefers-reduced-motion: reduce) {
.adaptive-component {
transition: none;
animation: none;
}
}
Best Practices
- Use consistent breakpoints throughout your project by defining them as variables.
- Design mobile-first by starting with base styles and adding larger screen styles progressively.
- Group related responsive styles within the same
media()function call for better organization. - Leverage the context parameter to access all styleframe functions within media queries.
- Test across devices to ensure your responsive design works as expected.
FAQ
media() function supports all standard CSS media query features including min-width, max-width, orientation, prefers-color-scheme, and more.media() function.selector, variable, ref, and even nested media calls.rem units respect user font size preferences, while px units provide more predictable behavior. Choose based on your accessibility requirements.At-Rules
Styleframe at-rules enable you to create modern CSS features like container queries, feature detection, font loading, and more with full type safety and auto-complete support.
Keyframes
Styleframe keyframes enable you to create smooth CSS animations with type-safe property definitions. Build engaging motion effects that enhance user experience across your application.