Skip to content

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