CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fluentui--merge-styles

Runtime CSS-in-JavaScript utilities for dynamic styling with high performance, RTL support, and TypeScript integration.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

css-features.mddocs/

CSS Features

Support for advanced CSS features including @font-face declarations and @keyframes animations with automatic registration, deduplication, and name generation.

Capabilities

Font Face Registration

Registers @font-face declarations for custom fonts with automatic deduplication.

/**
 * Registers a @font-face declaration
 * @param font - Font face definition with src, family, and display properties
 */
function fontFace(font: IFontFace): void;

interface IFontFace extends IRawFontStyle {
  /** Font display strategy for loading behavior */
  fontDisplay?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional';
  /** OpenType feature settings */
  fontFeatureSettings?: string;
  /** Font source URLs or local references */
  src?: string;
  /** Unicode character range coverage */
  unicodeRange?: ICSSRule | string;
}

Usage Examples:

import { fontFace } from "@fluentui/merge-styles";

// Basic web font registration
fontFace({
  fontFamily: "MyCustomFont",
  src: `url('fonts/mycustomfont.woff2') format('woff2'),
        url('fonts/mycustomfont.woff') format('woff')`,
  fontWeight: "normal",
  fontStyle: "normal",
  fontDisplay: "swap"
});

// Font with multiple weights
fontFace({
  fontFamily: "Roboto",
  src: "url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700')",
  fontWeight: "300 700", // Variable weight range
  fontDisplay: "fallback"
});

// Font with Unicode range
fontFace({
  fontFamily: "IconFont",
  src: "url('icons/iconfont.woff2') format('woff2')",
  unicodeRange: "U+E000-E0FF", // Private use area
  fontDisplay: "block"
});

// Now use the registered font in styles
import { mergeStyles } from "@fluentui/merge-styles";

const customFontStyle = mergeStyles({
  fontFamily: "MyCustomFont, Arial, sans-serif"
});

Keyframes Animation

Creates and registers @keyframes animations, returning the generated animation name.

/**
 * Registers keyframe definitions and returns animation name
 * @param timeline - Object mapping keyframe selectors to style objects
 * @returns Generated animation name for use in CSS animations
 */
function keyframes(timeline: IKeyframes): string;

type IKeyframes = Record<string, IRawStyle>;

Usage Examples:

import { keyframes, mergeStyles } from "@fluentui/merge-styles";

// Simple fade-in animation
const fadeInAnimation = keyframes({
  "0%": { opacity: 0 },
  "100%": { opacity: 1 }
});

// Bounce animation with multiple keyframes
const bounceAnimation = keyframes({
  "0%, 20%, 53%, 80%, 100%": {
    transform: "translate3d(0, 0, 0)"
  },
  "40%, 43%": {
    transform: "translate3d(0, -30px, 0)"
  },
  "70%": {
    transform: "translate3d(0, -15px, 0)"
  },
  "90%": {
    transform: "translate3d(0, -4px, 0)"
  }
});

// Complex rotation and scale animation
const spinGrowAnimation = keyframes({
  "0%": {
    transform: "rotate(0deg) scale(1)",
    opacity: 1
  },
  "50%": {
    transform: "rotate(180deg) scale(1.2)",
    opacity: 0.8
  },
  "100%": {
    transform: "rotate(360deg) scale(1)",
    opacity: 1
  }
});

// Use animations in styles
const animatedStyle = mergeStyles({
  // Apply fade-in animation
  animation: `${fadeInAnimation} 0.3s ease-in-out`,
  
  ":hover": {
    // Apply bounce on hover
    animation: `${bounceAnimation} 0.6s ease-in-out`
  }
});

const loadingStyle = mergeStyles({
  animation: `${spinGrowAnimation} 2s linear infinite`
});

Complex Animation Examples

Advanced keyframes with transforms, filters, and multi-property animations:

// Loading spinner
const spinnerAnimation = keyframes({
  "0%": {
    transform: "rotate(0deg)"
  },
  "100%": {
    transform: "rotate(360deg)"
  }
});

// Pulse effect
const pulseAnimation = keyframes({
  "0%": {
    transform: "scale(1)",
    boxShadow: "0 0 0 0 rgba(0, 123, 255, 0.7)"
  },
  "70%": {
    transform: "scale(1.05)",
    boxShadow: "0 0 0 10px rgba(0, 123, 255, 0)"
  },
  "100%": {
    transform: "scale(1)",
    boxShadow: "0 0 0 0 rgba(0, 123, 255, 0)"
  }
});

// Typewriter effect
const typewriterAnimation = keyframes({
  "0%": {
    width: "0"
  },
  "100%": {
    width: "100%"
  }
});

// Slide and fade
const slideFromLeftAnimation = keyframes({
  "0%": {
    transform: "translateX(-100%)",
    opacity: 0
  },
  "100%": {
    transform: "translateX(0)",
    opacity: 1
  }
});

// Apply complex animations
const complexAnimationStyle = mergeStyles({
  // Base animation
  animation: `${slideFromLeftAnimation} 0.5s ease-out`,
  
  // Conditional animations with pseudo-classes
  "&.loading": {
    animation: `${spinnerAnimation} 1s linear infinite`
  },
  
  "&.pulsing": {
    animation: `${pulseAnimation} 2s infinite`
  },
  
  // Multiple animations
  "&.complex": {
    animation: `
      ${fadeInAnimation} 0.3s ease-in,
      ${pulseAnimation} 2s 0.3s infinite
    `
  }
});

Font Style Types

interface IRawFontStyle {
  font?: ICSSRule | string;
  fontFamily?: ICSSRule | string;
  fontKerning?: ICSSRule | string;
  fontSize?: ICSSRule | 'xx-small' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' | 'xx-large' | 'larger' | 'smaller' | ICSSPixelUnitRule | string;
  fontSizeAdjust?: ICSSRule | 'none' | number | string;
  fontStretch?: ICSSRule | 'normal' | 'ultra-condensed' | 'extra-condensed' | 'condensed' | 'semi-condensed' | 'semi-expanded' | 'expanded' | 'extra-expanded' | 'ultra-expanded' | string;
  fontStyle?: ICSSRule | 'normal' | 'italic' | 'oblique' | string;
  fontSynthesis?: ICSSRule | string;
  fontVariant?: ICSSRule | string;
  fontVariantAlternates?: ICSSRule | string;
  fontWeight?: IFontWeight | string;
}

type IFontWeight = ICSSRule | 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | 100 | '200' | 200 | '300' | 300 | '400' | 400 | '500' | 500 | '600' | 600 | '700' | 700 | '800' | 800 | '900' | 900;

type ICSSRule = 'initial' | 'inherit' | 'unset';
type ICSSPixelUnitRule = string | number;

Performance and Deduplication

Both fontFace and keyframes automatically deduplicate identical declarations:

// These calls will result in only one @font-face rule
fontFace({
  fontFamily: "MyFont",
  src: "url('font.woff2')"
});

fontFace({
  fontFamily: "MyFont", 
  src: "url('font.woff2')" // Same as above - no duplicate rule created
});

// Same keyframes will return the same animation name
const anim1 = keyframes({ "0%": { opacity: 0 }, "100%": { opacity: 1 } });
const anim2 = keyframes({ "0%": { opacity: 0 }, "100%": { opacity: 1 } });
// anim1 === anim2 (same generated name)

docs

configuration.md

css-features.md

index.md

style-merging.md

style-sets.md

stylesheet-management.md

tile.json