Responsive Styling with InlineStyle
Learn to create adaptive layouts that respond to different screen sizes and device capabilities.
Viewport-Based Styling
Adjust styles based on window dimensions:
typescript
import { InlineStyle } from "@briklab/lib/stylesheet";
class ResponsiveLayouts {
static getContainerStyle(): InlineStyle {
const width = window.innerWidth;
if (width < 480) {
// Mobile
return new InlineStyle({
width: "100%",
padding: "8px",
fontSize: "14px",
display: "block"
});
} else if (width < 768) {
// Tablet
return new InlineStyle({
width: "90%",
padding: "12px",
fontSize: "15px",
display: "flex"
});
} else {
// Desktop
return new InlineStyle({
width: "80%",
maxWidth: "1200px",
padding: "20px",
fontSize: "16px",
display: "grid"
});
}
}
static applyResponsiveLayout(element: HTMLElement) {
const updateLayout = () => {
this.getContainerStyle().applyTo(element);
};
updateLayout();
window.addEventListener("resize", updateLayout);
}
}
// Usage
const container = document.querySelector(".main-container");
if (container instanceof HTMLElement) {
ResponsiveLayouts.applyResponsiveLayout(container);
}Live demo of responsive design:
Console
No logs yet.
Breakpoint-Based Styling
Implement classic CSS breakpoints in JavaScript:
typescript
import { InlineStyle } from "@briklab/lib/stylesheet";
class Breakpoints {
static breakpoints = {
xs: 0,
sm: 480,
md: 768,
lg: 1024,
xl: 1280
};
static getBreakpoint(width: number): keyof typeof this.breakpoints {
if (width >= this.breakpoints.xl) return "xl";
if (width >= this.breakpoints.lg) return "lg";
if (width >= this.breakpoints.md) return "md";
if (width >= this.breakpoints.sm) return "sm";
return "xs";
}
static getGridStyle(): Record<string, Record<string, string>> {
return {
xs: { gridTemplateColumns: "1fr" },
sm: { gridTemplateColumns: "1fr 1fr" },
md: { gridTemplateColumns: "repeat(3, 1fr)" },
lg: { gridTemplateColumns: "repeat(4, 1fr)" },
xl: { gridTemplateColumns: "repeat(6, 1fr)" }
};
}
static applyGridStyle(element: HTMLElement) {
const updateGrid = () => {
const breakpoint = this.getBreakpoint(window.innerWidth);
const gridStyles = this.getGridStyle()[breakpoint];
new InlineStyle({
display: "grid",
gap: "16px",
...gridStyles
}).applyTo(element);
};
updateGrid();
window.addEventListener("resize", updateGrid);
}
}
// Usage
const grid = document.querySelector(".responsive-grid");
if (grid instanceof HTMLElement) {
Breakpoints.applyGridStyle(grid);
}Aspect Ratio Responsive Layouts
Maintain aspect ratios across different screen sizes:
typescript
import { InlineStyle } from "@briklab/lib/stylesheet";
class AspectRatioLayouts {
static createResponsiveBox(aspectRatio: number = 16 / 9) {
const container = new InlineStyle({
position: "relative",
width: "100%",
paddingBottom: `${(1 / aspectRatio) * 100}%`,
height: "0"
});
const content = new InlineStyle({
position: "absolute",
top: "0",
left: "0",
width: "100%",
height: "100%"
});
return { container, content };
}
static applyAspectRatio(
containerEl: HTMLElement,
contentEl: HTMLElement,
ratio: number
) {
const { container, content } = this.createResponsiveBox(ratio);
container.applyTo(containerEl);
content.applyTo(contentEl);
}
}
// Usage
const videoContainer = document.querySelector(".video-container");
const videoContent = document.querySelector(".video-content");
if (videoContainer instanceof HTMLElement && videoContent instanceof HTMLElement) {
AspectRatioLayouts.applyAspectRatio(videoContainer, videoContent, 16 / 9);
}Orientation-Aware Styles
Adapt styles based on device orientation:
typescript
import { InlineStyle } from "@briklab/lib/stylesheet";
class OrientationStyles {
static getOrientationStyle(): InlineStyle {
const isPortrait = window.matchMedia("(orientation: portrait)").matches;
if (isPortrait) {
return new InlineStyle({
width: "100%",
height: "auto",
display: "flex",
flexDirection: "column"
});
} else {
return new InlineStyle({
width: "50%",
height: "100%",
display: "flex",
flexDirection: "row"
});
}
}
static applyOrientationStyles(element: HTMLElement) {
const updateStyles = () => {
this.getOrientationStyle().applyTo(element);
};
updateStyles();
window.addEventListener("orientationchange", updateStyles);
window.addEventListener("resize", updateStyles);
}
}
// Usage
const layout = document.querySelector(".orientation-aware");
if (layout instanceof HTMLElement) {
OrientationStyles.applyOrientationStyles(layout);
}Fluid Typography
Scale font sizes responsively:
typescript
import { InlineStyle } from "@briklab/lib/stylesheet";
class FluidTypography {
static calculateFluidFontSize(
minSize: number,
maxSize: number,
minViewport: number = 320,
maxViewport: number = 1280
): string {
const vmin = (minSize / 16) * 100;
const vmax = (maxSize / 16) * 100;
const slope = (maxSize - minSize) / (maxViewport - minViewport);
const intercept = minSize - slope * minViewport;
return `clamp(${minSize}px, ${intercept}px + ${slope * 100}vw, ${maxSize}px)`;
}
static applyFluidTypography(element: HTMLElement) {
const heading = new InlineStyle({
fontSize: this.calculateFluidFontSize(24, 48),
lineHeight: "1.2"
});
const body = new InlineStyle({
fontSize: this.calculateFluidFontSize(14, 18),
lineHeight: "1.6"
});
// Apply based on element
if (element.matches("h1, h2, h3")) {
heading.applyTo(element);
} else {
body.applyTo(element);
}
}
}
// Usage
document.querySelectorAll("h1, h2, h3, p").forEach(el => {
if (el instanceof HTMLElement) {
FluidTypography.applyFluidTypography(el);
}
});Media Query Listeners
React to media query changes programmatically:
typescript
import { InlineStyle } from "@briklab/lib/stylesheet";
class MediaQueryListener {
static setupResponsiveTheme() {
const darkMode = window.matchMedia("(prefers-color-scheme: dark)");
const reduces Motion = window.matchMedia("(prefers-reduced-motion: reduce)");
const applyTheme = (isDark: boolean) => {
const style = new InlineStyle(
isDark
? {
backgroundColor: "#1e1e1e",
color: "#ffffff"
}
: {
backgroundColor: "#ffffff",
color: "#1e1e1e"
}
);
style.applyTo(document.body);
};
const applyMotionPreference = (prefersReduced: boolean) => {
const style = new InlineStyle(
prefersReduced
? { transition: "none", animation: "none" }
: {}
);
style.applyTo(document.documentElement);
};
// Initial apply
applyTheme(darkMode.matches);
applyMotionPreference(reducesMotion.matches);
// Listen for changes
darkMode.addListener(e => applyTheme(e.matches));
reducesMotion.addListener(e => applyMotionPreference(e.matches));
}
}
// Usage
MediaQueryListener.setupResponsiveTheme();Flexbox Responsive Layouts
Create responsive flex containers:
typescript
import { InlineStyle } from "@briklab/lib/stylesheet";
class FlexLayouts {
static createResponsiveFlex() {
const wrapper = new InlineStyle({
display: "flex",
flexWrap: "wrap",
gap: "16px"
});
const updateFlex = (element: HTMLElement) => {
const width = window.innerWidth;
const direction = width < 768 ? "column" : "row";
const justify = width < 1024 ? "flex-start" : "space-between";
new InlineStyle({
display: "flex",
flexDirection: direction,
justifyContent: justify,
gap: "16px"
}).applyTo(element);
};
return { wrapper, updateFlex };
}
static applyResponsiveFlex(element: HTMLElement) {
const { updateFlex } = this.createResponsiveFlex();
updateFlex(element);
window.addEventListener("resize", () => updateFlex(element));
}
}
// Usage
const flexContainer = document.querySelector(".flex-layout");
if (flexContainer instanceof HTMLElement) {
FlexLayouts.applyResponsiveFlex(flexContainer);
}Next Steps
- Inline Styles: Basic style application
- Dynamic Themes: Theme switching
- StyleSheet Class: Global styles
- Examples: Real-world patterns