Skip to content

Card

Cards are flexible and extensible content containers. They include options for headers and footers, a wide variety of content, contextual background colors, and powerful display options.

Bootstrap Reference

Bootstrap 5 Card Documentation


Quick Start

Live Preview
Featured
A simple card with some content.
Card(
    "A simple card with some content.",
    header="Featured",
    footer=Button("Go somewhere")
)

Visual Examples & Use Cases

1. Images & Structure

Cards commonly contain images at the top (img_top) or bottom (img_bottom).

Live Preview
...
Card Image Cap

Some quick example text to build on the card title.

Card(
    "Some quick example text to build on the card title.",
    title="Card Image Cap",
    img_top="https://placehold.co/600x400",
    footer="Last updated 3 mins ago"
)

2. Semantic Variants

Apply background colors with text-bg-{variant} classes by using the variant argument.

Code & Output

Live Preview
Success

Success Card

Error

Danger Card

Dark

Dark Card

Card("Success Card", title="Success", variant="success")
Card("Danger Card", title="Error", variant="danger")
Card("Dark Card", title="Dark", variant="dark")

3. Slot Class Customization 🛠️

FastStrap Cards have specialized "slots" for customization. You don't have to overwrite the base classes; just inject your own into specific parts.

Slot Param Targeting Description
header_cls .card-header Styles the header container.
body_cls .card-body Styles the main content area.
footer_cls .card-footer Styles the footer.
title_cls .card-title Styles the H5 title.
Live Preview
My Title
Content...
# A card with a blue header and padded body
Card(
    "Content...",
    header="My Title",
    header_cls="bg-primary text-white text-center",
    body_cls="p-5 fs-4"
)

Parameter Reference

faststrap.components.display.card.Card(*children, title=None, subtitle=None, header=None, footer=None, img_top=None, img_bottom=None, img_overlay=False, header_cls=UNSET, body_cls=UNSET, footer_cls=UNSET, title_cls=None, subtitle_cls=None, text_cls=None, header_attrs=None, body_attrs=None, footer_attrs=None, title_attrs=None, subtitle_attrs=None, text_attrs=None, **kwargs)

Bootstrap Card component for flexible content containers.

Parameters:

Name Type Description Default
*children Any

Card body content

()
title str | None

Card title (styled with card-title)

None
subtitle str | None

Card subtitle (styled with card-subtitle)

None
header Any | None

Card header content (separate section above body)

None
footer Any | None

Card footer content (separate section below body)

None
img_top str | None

Image URL for top of card

None
img_bottom str | None

Image URL for bottom of card

None
img_overlay bool

Use image as background with overlay text

False
header_attrs dict[str, Any] | None

Extra attributes for the header wrapper

None
body_attrs dict[str, Any] | None

Extra attributes for the body wrapper

None
footer_attrs dict[str, Any] | None

Extra attributes for the footer wrapper

None
title_attrs dict[str, Any] | None

Extra attributes for the title element

None
subtitle_attrs dict[str, Any] | None

Extra attributes for the subtitle element

None
text_attrs dict[str, Any] | None

Extra attributes for the text wrapper

None
**kwargs Any

Additional HTML attributes (cls, id, hx-, data-, etc.)

{}

Returns:

Type Description
Div

FastHTML Div element with card structure

Examples:

Basic card:

>>> Card("Card content", title="Card Title")

With header and footer:

>>> Card(
...     "Main content",
...     title="Title",
...     header="Featured",
...     footer="Last updated 3 mins ago"
... )
Source code in src/faststrap/components/display/card.py
@register(category="display")
@stable
def Card(
    *children: Any,
    title: str | None = None,
    subtitle: str | None = None,
    header: Any | None = None,
    footer: Any | None = None,
    img_top: str | None = None,
    img_bottom: str | None = None,
    img_overlay: bool = False,
    header_cls: str | None = UNSET,
    body_cls: str | None = UNSET,
    footer_cls: str | None = UNSET,
    title_cls: str | None = None,
    subtitle_cls: str | None = None,
    text_cls: str | None = None,
    header_attrs: dict[str, Any] | None = None,
    body_attrs: dict[str, Any] | None = None,
    footer_attrs: dict[str, Any] | None = None,
    title_attrs: dict[str, Any] | None = None,
    subtitle_attrs: dict[str, Any] | None = None,
    text_attrs: dict[str, Any] | None = None,
    **kwargs: Any,
) -> Div:
    """Bootstrap Card component for flexible content containers.

    Args:
        *children: Card body content
        title: Card title (styled with card-title)
        subtitle: Card subtitle (styled with card-subtitle)
        header: Card header content (separate section above body)
        footer: Card footer content (separate section below body)
        img_top: Image URL for top of card
        img_bottom: Image URL for bottom of card
        img_overlay: Use image as background with overlay text
        header_attrs: Extra attributes for the header wrapper
        body_attrs: Extra attributes for the body wrapper
        footer_attrs: Extra attributes for the footer wrapper
        title_attrs: Extra attributes for the title element
        subtitle_attrs: Extra attributes for the subtitle element
        text_attrs: Extra attributes for the text wrapper
        **kwargs: Additional HTML attributes (cls, id, hx-*, data-*, etc.)

    Returns:
        FastHTML Div element with card structure

    Examples:
        Basic card:
        >>> Card("Card content", title="Card Title")

        With header and footer:
        >>> Card(
        ...     "Main content",
        ...     title="Title",
        ...     header="Featured",
        ...     footer="Last updated 3 mins ago"
        ... )
    """
    # Resolve defaults
    cfg = resolve_defaults(
        "Card",
        header_cls=header_cls,
        body_cls=body_cls,
        footer_cls=footer_cls,
    )

    c_title = title
    c_subtitle = subtitle
    c_header = header
    c_footer = footer
    c_img_top = img_top
    c_img_bottom = img_bottom
    c_img_overlay = img_overlay

    # CSS classes (fallback to empty string if None)
    c_header_cls = cfg.get("header_cls") or ""
    c_body_cls = cfg.get("body_cls") or ""
    c_footer_cls = cfg.get("footer_cls") or ""
    c_title_cls = title_cls or ""
    c_subtitle_cls = subtitle_cls or ""
    c_text_cls = text_cls or ""
    c_header_attrs = convert_attrs(dict(header_attrs or {}))
    c_body_attrs = convert_attrs(dict(body_attrs or {}))
    c_footer_attrs = convert_attrs(dict(footer_attrs or {}))
    c_title_attrs = convert_attrs(dict(title_attrs or {}))
    c_subtitle_attrs = convert_attrs(dict(subtitle_attrs or {}))
    c_text_attrs = convert_attrs(dict(text_attrs or {}))

    # Build base classes
    classes = ["card"]

    # Merge with user classes
    user_cls = kwargs.pop("cls", "")
    all_classes = merge_classes(" ".join(classes), user_cls)

    # Build attributes
    attrs: dict[str, Any] = {"cls": all_classes}
    attrs.update(convert_attrs(kwargs))

    # Build card structure
    parts = []

    # Add header if provided
    if c_header:
        parts.append(
            Div(
                c_header,
                cls=merge_classes("card-header", c_header_cls, c_header_attrs.pop("cls", "")),
                **c_header_attrs,
            )
        )

    # Add top image
    if c_img_top and not c_img_overlay:
        parts.append(Img(src=c_img_top, cls="card-img-top", alt=""))

    # Build body content
    body_content = []

    # Add image for overlay mode
    if c_img_overlay and c_img_top:
        parts.append(Img(src=c_img_top, cls="card-img", alt=""))
        actual_body_cls = "card-img-overlay"
    else:
        actual_body_cls = "card-body"

    # Add title
    if c_title:
        body_content.append(
            H5(
                c_title,
                cls=merge_classes("card-title", c_title_cls, c_title_attrs.pop("cls", "")),
                **c_title_attrs,
            )
        )

    # Add subtitle
    if c_subtitle:
        body_content.append(
            Div(
                c_subtitle,
                cls=merge_classes(
                    "card-subtitle mb-2 text-muted",
                    c_subtitle_cls,
                    c_subtitle_attrs.pop("cls", ""),
                ),
                **c_subtitle_attrs,
            )
        )

    # Add main content
    if children:
        # If there's a title/subtitle, wrap content in P for better semantics
        if c_title or c_subtitle:
            body_content.append(
                Div(
                    *children,
                    cls=merge_classes("card-text", c_text_cls, c_text_attrs.pop("cls", "")),
                    **c_text_attrs,
                )
            )
        else:
            body_content.extend(children)

    # Add body
    if body_content:
        parts.append(
            Div(
                *body_content,
                cls=merge_classes(actual_body_cls, c_body_cls, c_body_attrs.pop("cls", "")),
                **c_body_attrs,
            )
        )

    # Add bottom image
    if c_img_bottom and not c_img_overlay:
        parts.append(Img(src=c_img_bottom, cls="card-img-bottom", alt=""))

    # Add footer
    if c_footer:
        parts.append(
            Div(
                c_footer,
                cls=merge_classes(
                    "card-footer text-muted",
                    c_footer_cls,
                    c_footer_attrs.pop("cls", ""),
                ),
                **c_footer_attrs,
            )
        )

    return Div(*parts, **attrs)