astrojs

Passing a class to the generated picture alement Astro <Picture /> component


I'm trying to use the component that astro provides via the astro::assets import. Whenever i try to pass i class to the component it gets rendered on the img tag in the DOM. Is there any way i can pass a class to the generated picture element in the DOM?

This is the component file i'm using:

---
import { Picture } from "astro:assets";

interface Props {
    src: ImageMetadata;
    alt: string;
    sizes: string;
    class?: string;
}

const { src, alt, sizes, class: className, ...props } = Astro.props

---
<Picture
    class:list={["c-image", className]} 
    src={src} 
    alt={alt}
    loading="lazy"
    formats={["webp", "avif"]}
    widths={[640, 768, 1024, 1366, 1600, 1920, src.width]}
    sizes={sizes}
    {...props}
/>

<style scoped lang="scss">
    .c-image {
        width: 100%;
        display: block;

        &--cover {
            object-fit: cover;
            object-position: center;
        }
    }
</style>

DOM result


Solution

  • I had the same issue, it turns out the class is being passed, not just as one might expect...

    So using the component like this: <Picture class="myclass" ...> Does not generate:

    <picture class="myclass">
      ...
      <img ...>
    </picture>
    

    But rather

    <picture>
      ...
      <img class="myclass">
    </picture>
    

    So there are two options for styling:

    1. Use :has to apply styles to the targeted picture element instead of the img element.
    picture:has(> .c-image) {
      width: 100%;
      display: block;
    }
    
    1. Apply display: contents to the picture element to remove its box and have the img element behave as a direct child
    picture {
      display: contents;
    }
    
    .c-image {
      width: 100%;
      display: block;
    }