Working with grids with slots is difficult due to missing Astro CSS

Created on 27 February 2025, 3 months ago

Overview

I have a component that uses slots. The challenge is that inside the slot, Astro adds an <astro-slot> element, which breaks the grid handling. To mitigate this, Astro recommends adding following CSS:

astro-island, astro-slot, astro-static-slot {
  display:contents;
}

However, this conflicts with XBs annotation handling which has the following code:

[data-xb-slot-id], [data-xb-region], [data-xb-region] > .region {
    position: relative;
    display: flow-root;
}

This is the component I have built:

import { cva } from "class-variance-authority";
import { cn } from "@/lib/utils";

const gridVariants = cva(
  "mx-auto grid w-full max-w-[1360px] place-items-center gap-4",
  {
    variants: {
      cardLayout: {
        "2 columns": "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-2",
        "3 columns": "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3",
        "4 columns": "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4",
        "6 columns": "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-6",
      },
    },
    defaultVariants: {
      cardLayout: "3 column",
    },
  },
);

const CardContainer = ({
  heading,
  cardLayout,
  cards,
}) => {
  return (
    <div className="my-18 flex flex-col items-center gap-16 md:my-24">
      {heading}
      <div className={cn(gridVariants({ cardLayout }))}>{cards}</div>
    </div>
  );
};


export default CardContainer;

Proposed resolution

User interface changes

🐛 Bug report
Status

Active

Version

0.0

Component

Theme builder

Created by

🇫🇮Finland lauriii Finland

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @lauriii
  • 🇫🇮Finland lauriii Finland
  • 🇬🇧United Kingdom jessebaker

    Adding:

    astro-island, astro-slot, astro-static-slot {
      display:contents;
    }
    

    breaks both the Overlay and SortableJS meaning you basically can't use XB!

    The overlay (for both slots and components) relies on being able to get the boundingClientRect of the components and slots it is mirroring but that doesn't work with display:contents as those elements then have no box size. This can possibly be worked around by detecting that CSS and instead basing the overlay size on the combined size of the children of the element.

    SortableJS must have some internal check for the sortable items' size too because as soon as you add display: contents to the sortable items they stop working.

  • 🇺🇸United States effulgentsia

    I think the fix for this is to add a JS file to the astro.hydration library that adds an event handler for the astro:only event that Astro fires after hydration completes, and in this event handler, remove the <astro-slot> and <astro-island> wrapper elements (i.e., remove them as wrappers by moving their children up to their parent). This would then match what SSR will do once we add SSR support. This would only be for components that don't depend on client state. Reactive components would still need these wrappers. But so long as this works for non-reactive components, people can solve grid issues by, for example, nesting non-reactive grid container components inside a reactive component that needs a grid.

    In the meantime, the specific component in the issue summary can be made to work with this trick:

    const gridVariants = cva(
    -  "mx-auto grid w-full max-w-[1360px] place-items-center gap-4",
    +  "mx-auto grid w-full max-w-[1360px] place-items-center gap-4 [&>astro-slot]:grid [&>astro-slot]:grid-cols-subgrid",
      {
        variants: {
          cardLayout: {
    -        "2 columns": "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-2",
    +        "2 columns": "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-2 [&>astro-slot]:col-span-2",
    

    Hat tip to @lauriii, @larowlan, and @balintbrews for figuring out the above subgrid approach.

  • 🇬🇧United Kingdom jessebaker

    RE #3 - The sortableJS limitation/issue is not a problem any more as the work in 📌 Investigate drag-and-drop solution that removes the need to drop items into the preview iFrame Active has replaced SortableJS with DnDKit and no longer relies on the markup of elements in the iFrame for drag and drop.

    Adding display: contents to the astro-islands does still break the overlay even in that new solution - however it would just be one problem to solve now (detect astro-islands and base the size of the overlay on the immediate child instead).

    The alternative, proposed by @effulgentsia in #4 is also seemingly a viable route.

    I'd be interested in hearing @balintbrews' thoughts on this and which solution he favours?

  • Merge request !930Add client.css to astro build → (Merged) created by jessebaker
  • Pipeline finished with Success
    29 days ago
    #479246
  • Pipeline finished with Success
    29 days ago
    Total: 1723s
    #479323
  • Pipeline finished with Failed
    29 days ago
    Total: 1849s
    #479405
  • Pipeline finished with Success
    27 days ago
    Total: 571s
    #481421
  • 🇺🇸United States effulgentsia

    I recommend renaming client.css to hydration.css, since it's part of the hydration library, not the client library. Note that the hydration library is independent of UI framework, whereas the client library is specific to Preact.

    Also, as part of this issue, can we add header: true to the astro.hydration library, similar to how we do for the xb-ui library? That will ensure that the <astro-*> custom elements begin in an upgraded state, reducing layout shift on the actual site, and possibly also helping with 🐛 Overlay and iFrame flicker on updating props values Active while editing within XB.

  • Pipeline finished with Success
    26 days ago
    Total: 933s
    #481880
  • Pipeline finished with Canceled
    23 days ago
    #483703
  • Pipeline finished with Failed
    23 days ago
    #483705
  • Status changed to Needs review 22 days ago
  • First commit to issue fork.
  • Pipeline finished with Failed
    22 days ago
    Total: 558s
    #485088
  • 🇺🇸United States hooroomoo

    Neat

  • 🇺🇸United States hooroomoo

    FYI there's an existing bug right now where slots on a JS component don't appear until after you publish it 🐛 JS component slots don't appear in the preview canvas until published Active

    This looks good to me though

  • 🇳🇱Netherlands balintbrews Amsterdam, NL
  • Pipeline finished with Success
    22 days ago
    Total: 768s
    #485210
  • Pipeline finished with Skipped
    22 days ago
    #485215
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024