svg

SVG utilities for Tailwind CSS

Fill

The fill utility controls the fill color of SVG elements. It supports all Tailwind color families and shades, as well as special color values.

Exported source
fill_none = SingleValueFactory("fill-none", "Remove fill from an element") # Remove fill
Exported source
fill = ColoredFactory("fill", "Fill color utilities for styling the fill of SVG elements") # The fill color factory

Basic Fill Colors

Apply fill colors using the standard color palette:


test_svg_fill_examples


def test_svg_fill_examples(
    
):

Test fill color utilities with various color values.

Exported source
def test_svg_fill_examples():
    """Test fill color utilities with various color values."""
    # Test standard colors
    assert str(fill.red._500) == "fill-red-500"
    assert str(fill.blue._300) == "fill-blue-300"
    assert str(fill.green._700) == "fill-green-700"
    assert str(fill.purple._400) == "fill-purple-400"
    
    # Test all 22 color families
    assert str(fill.red._500) == "fill-red-500"
    assert str(fill.orange._500) == "fill-orange-500"
    assert str(fill.amber._500) == "fill-amber-500"
    assert str(fill.yellow._500) == "fill-yellow-500"
    assert str(fill.lime._500) == "fill-lime-500"
    assert str(fill.green._500) == "fill-green-500"
    assert str(fill.emerald._500) == "fill-emerald-500"
    assert str(fill.teal._500) == "fill-teal-500"
    assert str(fill.cyan._500) == "fill-cyan-500"
    assert str(fill.sky._500) == "fill-sky-500"
    assert str(fill.blue._500) == "fill-blue-500"
    assert str(fill.indigo._500) == "fill-indigo-500"
    assert str(fill.violet._500) == "fill-violet-500"
    assert str(fill.purple._500) == "fill-purple-500"
    assert str(fill.fuchsia._500) == "fill-fuchsia-500"
    assert str(fill.pink._500) == "fill-pink-500"
    assert str(fill.rose._500) == "fill-rose-500"
    assert str(fill.slate._500) == "fill-slate-500"
    assert str(fill.gray._500) == "fill-gray-500"
    assert str(fill.zinc._500) == "fill-zinc-500"
    assert str(fill.neutral._500) == "fill-neutral-500"
    assert str(fill.stone._500) == "fill-stone-500"
    
    # Test special colors
    assert str(fill_none) == "fill-none"
    assert str(fill.inherit) == "fill-inherit"
    assert str(fill.current) == "fill-current"
    assert str(fill.transparent) == "fill-transparent"
    assert str(fill.black) == "fill-black"
    assert str(fill.white) == "fill-white"

# Run the tests
test_svg_fill_examples()

Fill with Opacity

Control the opacity of fill colors:


test_svg_fill_opacity_examples


def test_svg_fill_opacity_examples(
    
):

Test fill colors with opacity modifiers.

Exported source
def test_svg_fill_opacity_examples():
    """Test fill colors with opacity modifiers."""
    # Standard opacity values
    assert str(fill.red._500.opacity(50)) == "fill-red-500/50"
    assert str(fill.blue._300.opacity(75)) == "fill-blue-300/75"
    assert str(fill.black.opacity(10)) == "fill-black/10"
    
    # Arbitrary opacity values
    assert str(fill.green._600.opacity("[0.87]")) == "fill-green-600/[0.87]"
    assert str(fill.purple._400.opacity("(--my-opacity)")) == "fill-purple-400/(--my-opacity)"

# Run the tests
test_svg_fill_opacity_examples()

Arbitrary Fill Values

Use custom colors when needed:


test_svg_fill_arbitrary_examples


def test_svg_fill_arbitrary_examples(
    
):

Test fill utilities with arbitrary and custom values.

Exported source
def test_svg_fill_arbitrary_examples():
    """Test fill utilities with arbitrary and custom values."""
    # Arbitrary color values
    assert str(fill("#ff0000")) == "fill-[#ff0000]"
    assert str(fill("rgb(255, 0, 0)")) == "fill-[rgb(255, 0, 0)]"
    assert str(fill("hsl(0, 100%, 50%)")) == "fill-[hsl(0, 100%, 50%)]"
    
    # CSS custom properties
    assert str(fill("--custom-fill")) == "fill-(--custom-fill)"
    assert str(fill("--theme-primary")) == "fill-(--theme-primary)"

# Run the tests
test_svg_fill_arbitrary_examples()

Stroke

The stroke utility controls the stroke color of SVG elements. It supports the same color system as fill.

Exported source
stroke_none = SingleValueFactory("stroke-none", "Remove stroke from an element") # Remove stroke
Exported source
stroke = ColoredFactory("stroke", "Stroke color utilities for styling the stroke of SVG elements") # The stroke color factory

Basic Stroke Colors

Apply stroke colors using the standard color palette:


test_svg_stroke_examples


def test_svg_stroke_examples(
    
):

Test stroke color utilities with various color values.

Exported source
def test_svg_stroke_examples():
    """Test stroke color utilities with various color values."""
    # Test standard colors
    assert str(stroke.red._500) == "stroke-red-500"
    assert str(stroke.blue._300) == "stroke-blue-300"
    assert str(stroke.green._700) == "stroke-green-700"
    assert str(stroke.purple._400) == "stroke-purple-400"

    # Test all 22 color families
    assert str(stroke.red._500) == "stroke-red-500"
    assert str(stroke.orange._500) == "stroke-orange-500"
    assert str(stroke.amber._500) == "stroke-amber-500"
    assert str(stroke.yellow._500) == "stroke-yellow-500"
    assert str(stroke.lime._500) == "stroke-lime-500"
    assert str(stroke.green._500) == "stroke-green-500"
    assert str(stroke.emerald._500) == "stroke-emerald-500"
    assert str(stroke.teal._500) == "stroke-teal-500"
    assert str(stroke.cyan._500) == "stroke-cyan-500"
    assert str(stroke.sky._500) == "stroke-sky-500"
    assert str(stroke.blue._500) == "stroke-blue-500"
    assert str(stroke.indigo._500) == "stroke-indigo-500"
    assert str(stroke.violet._500) == "stroke-violet-500"
    assert str(stroke.purple._500) == "stroke-purple-500"
    assert str(stroke.fuchsia._500) == "stroke-fuchsia-500"
    assert str(stroke.pink._500) == "stroke-pink-500"
    assert str(stroke.rose._500) == "stroke-rose-500"
    assert str(stroke.slate._500) == "stroke-slate-500"
    assert str(stroke.gray._500) == "stroke-gray-500"
    assert str(stroke.zinc._500) == "stroke-zinc-500"
    assert str(stroke.neutral._500) == "stroke-neutral-500"
    assert str(stroke.stone._500) == "stroke-stone-500"
    
    # Test special colors
    assert str(stroke_none) == "stroke-none"
    assert str(stroke.inherit) == "stroke-inherit"
    assert str(stroke.current) == "stroke-current"
    assert str(stroke.transparent) == "stroke-transparent"
    assert str(stroke.black) == "stroke-black"
    assert str(stroke.white) == "stroke-white"

# Run the tests
test_svg_stroke_examples()

Stroke with Opacity

Control the opacity of stroke colors:


test_svg_stroke_opacity_examples


def test_svg_stroke_opacity_examples(
    
):

Test stroke colors with opacity modifiers.

Exported source
def test_svg_stroke_opacity_examples():
    """Test stroke colors with opacity modifiers."""
    # Standard opacity values
    assert str(stroke.red._500.opacity(50)) == "stroke-red-500/50"
    assert str(stroke.blue._300.opacity(75)) == "stroke-blue-300/75"
    assert str(stroke.black.opacity(10)) == "stroke-black/10"
    
    # Arbitrary opacity values
    assert str(stroke.green._600.opacity("[0.87]")) == "stroke-green-600/[0.87]"
    assert str(stroke.purple._400.opacity("(--my-opacity)")) == "stroke-purple-400/(--my-opacity)"

# Run the tests
test_svg_stroke_opacity_examples()

Stroke Width

The stroke-width utility controls the width of SVG strokes. It supports numeric values from 0-2 by default.


StrokeWidthFactory


def StrokeWidthFactory(
    
):

Factory for stroke-width utilities with restricted numeric scale (0-2).

Exported source
stroke_width = StrokeWidthFactory() # The stroke width factory

Basic Stroke Width

Apply stroke width values:


test_svg_stroke_width_examples


def test_svg_stroke_width_examples(
    
):

Test stroke width utilities with various values.

Exported source
def test_svg_stroke_width_examples():
    """Test stroke width utilities with various values."""
    # Test default numeric values (0-2)
    assert str(stroke_width(0)) == "stroke-0"
    assert str(stroke_width(1)) == "stroke-1"
    assert str(stroke_width(2)) == "stroke-2"
    
    # Test attribute access
    assert str(stroke_width._0) == "stroke-0"
    assert str(stroke_width._1) == "stroke-1"
    assert str(stroke_width._2) == "stroke-2"
    
    # Test values outside default range (treated as arbitrary)
    assert str(stroke_width(3)) == "stroke-[3]"
    assert str(stroke_width(0.5)) == "stroke-[0.5]"
    assert str(stroke_width(1.5)) == "stroke-[1.5]"
    assert str(stroke_width._4) == "stroke-[4]"

# Run the tests
test_svg_stroke_width_examples()

Arbitrary Stroke Width Values

Use custom stroke width values:


test_svg_stroke_width_arbitrary_examples


def test_svg_stroke_width_arbitrary_examples(
    
):

Test stroke width utilities with arbitrary and custom values.

Exported source
def test_svg_stroke_width_arbitrary_examples():
    """Test stroke width utilities with arbitrary and custom values."""
    # Arbitrary numeric values
    assert str(stroke_width("0.25")) == "stroke-[0.25]"
    assert str(stroke_width("10px")) == "stroke-[10px]"
    assert str(stroke_width("2rem")) == "stroke-[2rem]"
    
    # CSS custom properties
    assert str(stroke_width("--stroke-thin")) == "stroke-(--stroke-thin)"
    assert str(stroke_width("--stroke-thick")) == "stroke-(--stroke-thick)"

# Run the tests
test_svg_stroke_width_arbitrary_examples()

Practical Examples

Let’s see how to use these SVG utilities in real FastHTML components:


test_svg_fasthtml_examples


def test_svg_fasthtml_examples(
    
):

Test SVG utilities in practical FastHTML component examples.

Exported source
def test_svg_fasthtml_examples():
    """Test SVG utilities in practical FastHTML component examples."""
    from fasthtml.common import Div
    from fasthtml.svg import Svg, Circle, Rect, G, Path
    from cjm_fasthtml_tailwind.utilities.sizing import w, h
    from cjm_fasthtml_tailwind.utilities.layout import display_tw
    from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import gap, grid_display
    
    # Icon with fill color
    icon = Svg(
        Path(
            d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z",
            cls=str(fill.current)
        ),
        viewBox="0 0 24 24",
        cls=combine_classes(w(6), h(6), fill_none)
    )
    assert "fill-current" in icon.children[0].attrs['class']
    assert "fill-none" in icon.attrs['class']
    
    # Circle with stroke
    circle_svg = Svg(
        Circle(
            cx="50", cy="50", r="40",
            cls=combine_classes(
                fill.transparent,
                stroke.blue._500,
                stroke_width(2)
            )
        ),
        viewBox="0 0 100 100",
        cls=combine_classes(w(24), h(24))
    )
    circle_attrs = circle_svg.children[0].attrs['class']
    assert "fill-transparent" in circle_attrs
    assert "stroke-blue-500" in circle_attrs
    assert "stroke-2" in circle_attrs
    
    # Complex SVG with multiple elements
    complex_svg = Svg(
        G(
            Rect(
                x="10", y="10", width="80", height="80",
                cls=combine_classes(
                    fill.red._200,
                    stroke.red._600,
                    stroke_width(1)
                )
            ),
            Circle(
                cx="50", cy="50", r="20",
                cls=combine_classes(
                    fill.blue._400.opacity(75),
                    stroke.blue._700,
                    stroke_width(2)
                )
            )
        ),
        viewBox="0 0 100 100",
        cls=combine_classes(w(32), h(32))
    )
    rect_attrs = complex_svg.children[0].children[0].attrs['class']
    circle_attrs = complex_svg.children[0].children[1].attrs['class']
    assert "fill-red-200" in rect_attrs
    assert "stroke-red-600" in rect_attrs
    assert "stroke-1" in rect_attrs
    assert "fill-blue-400/75" in circle_attrs
    assert "stroke-blue-700" in circle_attrs
    assert "stroke-2" in circle_attrs
    
    # Return all examples in a grid layout
    return Div(
        icon,
        circle_svg,
        complex_svg,
        cls=combine_classes(grid_display, gap(5))
    )

# Run the tests
test_svg_fasthtml_examples()
test_func = test_svg_fasthtml_examples
app, rt = create_test_app()

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

SVG Icon Examples

Create reusable icon components:


test_svg_icon_fasthtml_examples


def test_svg_icon_fasthtml_examples(
    
):

Test creating reusable SVG icon components.

Exported source
def test_svg_icon_fasthtml_examples():
    """Test creating reusable SVG icon components."""
    from fasthtml.common import Div
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import w, h
    from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import items, justify, gap, grid_display, flex_display
    from cjm_fasthtml_tailwind.utilities.layout import display_tw
    
    # Helper function to create an icon
    def Icon(path_d: str, size: int = 6, color_cls: str = ""):
        """Create a reusable icon component."""
        return Svg(
            Path(d=path_d, cls=str(fill.current)),
            viewBox="0 0 24 24",
            cls=combine_classes(
                w(size), h(size),
                fill_none,
                stroke.current,
                stroke_width(2),
                color_cls
            )
        )
    
    # Home icon
    home_icon = Icon(
        "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6",
        size=8,
        color_cls="text-blue-500"
    )
    assert "w-8 h-8" in home_icon.attrs['class']
    assert "fill-none" in home_icon.attrs['class']
    assert "stroke-current" in home_icon.attrs['class']
    assert "stroke-2" in home_icon.attrs['class']
    assert "text-blue-500" in home_icon.attrs['class']
    
    # Check icon with custom colors
    check_icon = Div(
        Svg(
            Path(
                d="M5 13l4 4L19 7",
                cls=combine_classes(
                    fill_none,
                    stroke.green._500,
                    stroke_width(2)
                )
            ),
            viewBox="0 0 24 24",
            cls=combine_classes(w(5), h(5))
        ),
        cls=combine_classes(flex_display.inline, items.center, justify.center)
    )
    path_attrs = check_icon.children[0].children[0].attrs['class']
    assert "fill-none" in path_attrs
    assert "stroke-green-500" in path_attrs
    assert "stroke-2" in path_attrs
    
    # Return all examples in a grid layout
    return Div(
        home_icon,
        check_icon,
        cls=combine_classes(grid_display, gap(5))
    )

# Run the tests
test_svg_icon_fasthtml_examples()
test_func = test_svg_icon_fasthtml_examples
app, rt = create_test_app()

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

Progress Ring Example

Create a circular progress indicator:


test_svg_progress_ring_fasthtml_examples


def test_svg_progress_ring_fasthtml_examples(
    
):

Test creating a progress ring component.

Exported source
def test_svg_progress_ring_fasthtml_examples():
    """Test creating a progress ring component."""
    from fasthtml.common import Div
    from fasthtml.svg import Svg, Circle
    from cjm_fasthtml_tailwind.utilities.sizing import w, h
    from cjm_fasthtml_tailwind.utilities.layout import display_tw, position
    from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import gap, grid_display, flex_display
    
    # Progress ring component
    def ProgressRing(percentage: int, size: int = 120):
        """Create a circular progress indicator."""
        radius = 45
        circumference = 2 * 3.14159 * radius
        stroke_dashoffset = circumference - (percentage / 100) * circumference
        
        return Div(
            Svg(
                # Background circle
                Circle(
                    cx=str(size // 2),
                    cy=str(size // 2),
                    r=str(radius),
                    cls=combine_classes(
                        fill_none,
                        stroke.gray._200,
                        stroke_width(8)
                    )
                ),
                # Progress circle
                Circle(
                    cx=str(size // 2),
                    cy=str(size // 2),
                    r=str(radius),
                    cls=combine_classes(
                        fill_none,
                        stroke.blue._500,
                        stroke_width(8)
                    ),
                    style=f"stroke-dasharray: {circumference}; stroke-dashoffset: {stroke_dashoffset}; transform: rotate(-90deg); transform-origin: center;",
                ),
                viewBox=f"0 0 {size} {size}",
                cls=combine_classes(w(32), h(32))
            ),
            cls=combine_classes(position.relative, flex_display.inline)
        )
    
    # Test 75% progress
    progress_75 = ProgressRing(75)
    svg = progress_75.children[0]
    bg_circle = svg.children[0]
    progress_circle = svg.children[1]
    
    assert "fill-none" in bg_circle.attrs['class']
    assert "stroke-gray-200" in bg_circle.attrs['class']
    assert "stroke-[8]" in bg_circle.attrs['class']
    
    assert "fill-none" in progress_circle.attrs['class']
    assert "stroke-blue-500" in progress_circle.attrs['class']
    assert "stroke-[8]" in progress_circle.attrs['class']
    assert "stroke-dasharray" in progress_circle.attrs['style']
    
    # Create different progress examples
    progress_25 = ProgressRing(25)
    progress_50 = ProgressRing(50)
    progress_100 = ProgressRing(100)
    
    # Return all examples in a grid layout
    return Div(
        progress_25,
        progress_50,
        progress_75,
        progress_100,
        cls=combine_classes(grid_display, gap(5))
    )

# Run the tests
test_svg_progress_ring_fasthtml_examples()
test_func = test_svg_progress_ring_fasthtml_examples
app, rt = create_test_app()

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

Edge Cases and Special Values

Test edge cases and special SVG-specific values:


test_svg_edge_cases


def test_svg_edge_cases(
    
):

Test edge cases and special values for SVG utilities.

Helper Functions

Convenient functions for common SVG patterns:


svg_icon_classes


def svg_icon_classes(
    fill_color:Union=None, # Fill color class or utility
    stroke_color:Union=None, # Stroke color class or utility
    width:Union=2, # Stroke width value
    size:int=6, # Icon size (numeric value for w and h)
    extra_classes:str='', # Additional classes to include
)->str: # Combined class string for SVG icon

Generate common SVG icon classes.


test_svg_helper_functions


def test_svg_helper_functions(
    
):

Test SVG helper functions.