# Gallery Z > Gallery Z is a free, GPL-licensed WordPress plugin for filterable photo galleries in the block editor: category filters, five layouts (masonry, justified rows, grid, carousel, accordion), scroll reveal effects and a native lightbox. It is built on core blocks and the Interactivity API, loads about 3 KB of JavaScript to start and has no dependencies. Key facts: - Price: free (GPL-2.0-or-later). No pro version, license key or upsell. - Requirements: WordPress 6.6 or newer, PHP 7.4 or newer. Current version: 1.0.0. - Blocks: Filterable Gallery (the container), Gallery Filter (buttons or dropdown), Gallery Media Query (Media Library images by category), and a "Gallery Posts" Query Loop variation. - Layouts: masonry (shortest column first), justified rows, grid (cropped to a ratio or height), carousel (arrows incl. a mouse-following cursor, endless loop, autoplay), accordion (opens to the photo's own shape). - Scroll reveal: rise, fade, zoom, blur, tilt, wipe, pop, flip, slide, iris – staggered, pure CSS scroll-driven animations. - Lightbox: native , zooms from the thumbnail, dark / light / frosted themes, captions and counter. - Videos: Media Library files, YouTube, Vimeo, TikTok and Instagram next to photos. Paste a link into a gallery to add one. Hover plays a muted preview, a click plays it in the lightbox; until then only the poster image loads. - Performance: ~3 KB JavaScript and ~2.3 KB CSS to start, only on pages with a gallery; other parts load only where used. Lazy images in the right size; no layout shift. - WordPress integration: importers for Envira Gallery, NextGEN Gallery, Modula and FooGallery (Tools → Gallery Z import, or `wp gallery-z import`); Media Library column, filter and bulk actions for Gallery Categories; command palette commands; seven block patterns; a Gallery Category archive template; Abilities API abilities for AI agents (WordPress 6.9+). - Works without JavaScript (server-rendered), in block themes and classic themes. ## Pages - [Home](https://galleryz.xyz/): Free WordPress gallery plugin with category filters, masonry, justified rows, carousel, lightbox and scroll reveal effects. Built on core blocks, 3 KB of JavaScript. - [Layouts](https://galleryz.xyz/layouts/): Five WordPress gallery layouts in one block – masonry, justified rows, grid, carousel and accordion – plus scroll reveal effects. Try every option live. - [100 Photos](https://galleryz.xyz/100-photos/): A Gallery Z masonry gallery with 100 photos, a category filter and a lightbox: the first row loads at once, the rest lazily in the size it is shown at. - [Playground](https://galleryz.xyz/playground/): Try Gallery Z in your browser: switch layouts, columns, captions, hover effects, filter styles and the lightbox on a live WordPress gallery. No install needed. - [Download the plugin](https://galleryz.xyz/wp-content/uploads/gallery-z/gallery-z.zip): zip, install via Plugins → Add New → Upload. ## Docs - [Docs](https://galleryz.xyz/docs/): Gallery Z docs: getting started, every block option, the five layouts, editing tools, categories and the Media Library, importing from Envira, NextGEN, Modula and FooGallery, patterns, AI abilities and developer notes. - [Getting started](https://galleryz.xyz/docs/getting-started/): Install Gallery Z, add your first filterable gallery with the “Add filterable gallery” command, assign categories and connect the filter. Step by step. - [Blocks & options](https://galleryz.xyz/docs/blocks/): Reference for the Gallery Z blocks: Filterable Gallery, Gallery Filter, Gallery Media Query and the Gallery Posts variation, with every option, value and default. - [Layouts](https://galleryz.xyz/docs/layouts/): The five Gallery Z layouts – masonry, justified rows, grid, carousel and accordion – how each one works, its options, and scroll reveal effects. - [Editing](https://galleryz.xyz/docs/editing/): Working with Gallery Z in the block editor: Edit and Preview modes, filter preview, bulk categories, sorting, block transforms and command palette commands. - [Categories & Media Library](https://galleryz.xyz/docs/categories/): How Gallery Categories work in Gallery Z: the shared taxonomy, the Media Library column, filters and bulk actions, and the category checklist in the media modal. - [Switching from other plugins](https://galleryz.xyz/docs/switching/): Import galleries from Envira Gallery, NextGEN Gallery, Modula and FooGallery into Gallery Z: what is mapped, the WP-CLI command, replacement shortcodes and what is not carried over. - [Patterns & archive template](https://galleryz.xyz/docs/patterns/): The Gallery Z block patterns (portfolio, travel journal, food menu, team, carousels) and the Gallery Category Archive template for block themes. - [AI & Abilities API](https://galleryz.xyz/docs/abilities/): Gallery Z registers four WordPress Abilities API abilities for AI agents and MCP clients: list categories, find images, tag images and create galleries, with REST methods. - [Developers](https://galleryz.xyz/docs/developers/): Developer notes for Gallery Z: WP-CLI commands, the WordPress Playground blueprint, filters such as gallery_z_taxonomy_object_types, asset handles and performance. ## Blog - [Blog](https://galleryz.xyz/blog/): Practical articles about Gallery Z: custom styles, switching from other gallery plugins, performance without jQuery, filterable portfolios and AI agents. - [Custom styles for Gallery Z](https://galleryz.xyz/blog/custom-styles/): Style Gallery Z from your theme: the Theme button and Theme link filter styles, your own filter style with register_block_style, caption looks through CSS variables, a custom hover effect and theme.json per-block styles. Four tested examples. - [Switching from Envira, NextGEN, Modula or FooGallery](https://galleryz.xyz/blog/switching-gallery-plugins/): How the Gallery Z importer moves Envira, NextGEN, Modula and FooGallery galleries into draft pages: what carries over, what doesn’t, the replacement shortcodes, WP-CLI, and what the plugins cost. - [Why a gallery doesn’t need jQuery in 2026](https://galleryz.xyz/blog/gallery-without-jquery/): A native dialog lightbox, scroll-snap carousels, CSS grid and masonry, scroll-driven reveals: how Gallery Z starts at 3 KB of JavaScript, and what it measures on a 100-photo page. - [Filterable portfolios with posts and images in one gallery](https://galleryz.xyz/blog/filterable-portfolio/): A step-by-step tutorial: one Gallery Z gallery with project posts, hand-picked images and a Media Library query, one category filter for all of them, and links that open the page already filtered. - [Letting AI agents build galleries: the Abilities API](https://galleryz.xyz/blog/ai-abilities/): Gallery Z registers four WordPress abilities: list categories, find images, tag images and create a gallery page. What each does, the REST routes and methods, permissions, and practical uses. ## Demos - [Demos](https://galleryz.xyz/demos/): Live demos of WordPress galleries made with Gallery Z: artist and illustration portfolios, wedding, real estate, restaurant, tattoo, florist, event and ceramics galleries, and TikTok, Instagram and YouTube Shorts. - [TikTok gallery](https://galleryz.xyz/demos/tiktok-gallery/): Show TikTok videos in a WordPress gallery: paste links, get a 9:16 grid with muted hover previews and a lightbox player. No API key, and nothing loads from TikTok until a click. - [Instagram gallery](https://galleryz.xyz/demos/instagram-gallery/): Hand-pick Instagram reels and posts for a WordPress gallery: paste links, get their cover images as posters, open them in a lightbox. No feed sync, no access token, no account to connect. - [YouTube Shorts gallery](https://galleryz.xyz/demos/youtube-shorts-gallery/): Put YouTube Shorts in a WordPress gallery: vertical posters, muted previews on hover and playback in a lightbox from youtube-nocookie.com. Mix with photos, YouTube and TikTok. - [Artist portfolio](https://galleryz.xyz/demos/artist-portfolio/): A WordPress portfolio gallery for painters and artists: justified rows that never crop a canvas, a filter by series or subject, and a lightbox with title and year. Live demo with Impressionist paintings. - [Illustration portfolio](https://galleryz.xyz/demos/illustration-portfolio/): A masonry portfolio for illustrators, studios and agencies: one tab per artist, captions on hover and a lightbox. Live demo with prints by Hokusai, Hiroshige and Toulouse-Lautrec. - [Wedding photography](https://galleryz.xyz/demos/wedding-photography-gallery/): A wedding gallery for photographers: ceremony, portraits, details and party as filter chapters, masonry or justified rows, and a swipeable lightbox. Live demo. - [Real estate listing](https://galleryz.xyz/demos/real-estate-gallery/): A property gallery for real estate listings: a carousel of the house with a filter by room, arrows on the photos and swipe on phones. No slider library. Live demo. - [Restaurant menu](https://galleryz.xyz/demos/restaurant-menu-gallery/): A menu gallery for restaurants and cafés: dishes in a square grid with names below, a filter for starters, mains, desserts and drinks, and a lightbox. Live demo. - [Tattoo portfolio](https://galleryz.xyz/demos/tattoo-portfolio/): A portfolio for tattoo studios: healed work in a 4:5 grid, filtered by style or artist with counts, plus Instagram posts if you like. Live demo. - [Fashion lookbook](https://galleryz.xyz/demos/fashion-lookbook/): A lookbook for fashion brands and stylists: an accordion that opens each look to its own shape on hover, with names on the photos. Live demo. - [Florist gallery](https://galleryz.xyz/demos/florist-gallery/): A gallery for florists: bouquets, wedding flowers, workshops and the shop in masonry with a filter. Add workshop videos from YouTube or Instagram. Live demo. - [Event photos](https://galleryz.xyz/demos/event-photo-gallery/): An event and conference photo gallery: talks, workshops, networking and audience in justified rows with a filter, fast with hundreds of photos. Live demo. - [Ceramics portfolio](https://galleryz.xyz/demos/ceramics-portfolio/): A portfolio gallery for ceramicists and makers: mugs, bowls and vases in a square grid with captions, filtered by type, linked to your shop if you like. Live demo. ## FAQ ### Can I filter a WordPress gallery by category? Yes, that is what Gallery Z is for. Put a Gallery Filter block next to a Filterable Gallery and visitors filter the photos by the categories you assigned, with an animated transition. The selection can optionally be shared in the URL, like ?category=nature. Step by step: Getting started. ### How is it different from the core Gallery block? The core Gallery block shows one grid. Gallery Z adds category filters, five layouts (masonry, justified rows, grid, carousel and accordion), scroll reveal effects, a lightbox that pages through the visible photos, and posts or Media Library queries as gallery items. Inside, the photos stay regular Image blocks. See Blocks & options. ### Will it slow down my site? No. A page with a gallery loads about 3 KB of JavaScript to start and 2.3 KB of CSS; carousel, accordion, lightbox and effect code loads only where a gallery uses it, and nothing loads on pages without a gallery. Images lazy-load in the right size, and masonry is placed before the first paint, so nothing shifts. The details are in the performance notes. ### Does it work with my theme? Yes. Gallery Z uses block supports and your theme’s own styles: filter buttons start from the theme’s button style, captions from its caption style, spacing from its gap. It works in block themes and in classic themes that use the block editor. ### How do the categories work? Gallery Z adds a Gallery Categories taxonomy that media, posts and pages share. Assign categories in the image sidebar inside a gallery or in the Media Library. Many images at once? Use the bulk actions in the Media Library. A gallery can also filter by any other taxonomy, such as regular post categories. More in Categories & Media Library. ### Can I switch from Envira, NextGEN, Modula or FooGallery? Yes. Under Tools → Gallery Z import (or with wp gallery-z import), each gallery becomes a draft page with a Filterable Gallery: images, captions, alt text, links and columns come along, and tags become filter categories. Lightbox themes, spacing and hover effects are not carried over. See Switching from other plugins. ### Can I show posts instead of images? Yes. Put a Query Loop inside the gallery – there is a “Gallery Posts” variation – and the featured images become gallery items with their titles as captions. Images, posts and Media Library queries can be mixed in one gallery. See Gallery Posts. ### What happens without JavaScript? Every item shows, rows and grids keep their layout (masonry becomes a plain column grid), and links still work. Lightbox links point to the full image file. See How it works. ### Which browsers are supported? All current browsers. View Transitions, @starting-style, color-mix(), scroll-driven animations and backdrop-filter are progressive enhancements: older browsers get the same features with simpler animations. ### What does it need? WordPress 6.6 or newer and PHP 7.4 or newer. No build step, no API keys, no external services. ### Is it really free? Yes. Gallery Z is licensed under the GPL v2 or later. There is no pro version, no license key and no upsell. ## Plugin reference ## Gallery Z Filterable gallery blocks for the WordPress block editor: masonry, justified rows and grid layouts, a separate filter block, a native lightbox, and images mixed with post or media queries. ### Blocks | Block | What it does | | --- | --- | | `gallery-z/gallery` – Filterable Gallery | Container with five layouts: **masonry** (shortest column first, reading order kept), **rows** (justified, rows break where the height fits best), **grid** (cropped to an aspect ratio or a fixed height), **carousel** (scroll-snap row: arrows on or below the photos or following the mouse, with their own icon, shape, look, size and colors, step, stop/rewind/endless loop, fixed slide count, centered current slide, autoplay) and **accordion** (slices that open to their photo's own width on hover or click, vertical on phones; with more photos than fit at 2.5rem a slice, the strip pans slowly with the mouse, no scrollbar, and swipes on touch). **Reveal on scroll** effects (rise, fade, zoom, blur, tilt, wipe, pop, flip, slide in from alternating sides, iris; the carousel reveals sideways) (scroll-driven animation, no JS), staggered so neighbors come in one after another rather than a row at once (**Stagger** slider, 0–6: the scroll distance between neighbors; 0 brings a row in together). Items animate over the same scroll distance whatever their height, and the reveal plays in the editor's Preview mode. Columns, row height and aspect ratio per device (desktop, tablet <782px, mobile <600px) with a device switcher tied to the editor preview. Click behavior: link (default; follows each image's own link, and the sidebar warns when no image has one), lightbox, media file, none. Defaults: zoom on hover, no captions. Filter animation: move + fade, slide, zoom, crossfade or none. | | `gallery-z/filter` – Gallery Filter | Buttons or a dropdown that filter one gallery (by Gallery ID) or every gallery on the page. Styles: Theme button (default, uses `wp-element-button`), Theme link (the theme's link color, hover and underline from its global styles), Soft, Pills, Segmented, Underline. Sizes XS–L or theme size, gap (default 0.5rem; 1.5em for Underline and Theme link, which have no padding), counts (inline/badge; worked out on the server when the galleries are image blocks in the same post, so counts are in the first paint and empty terms are left out instead of hidden after load), multi-select, hide empty, dropdown on mobile, URL sync (`?filter=nature`, also rendered server-side). Typography, border, shadow and the "Button" color apply to the buttons. | | `gallery-z/media-query` – Gallery Media Query | Media Library images by Gallery Category, inside a gallery. | | `core/query` variation "Gallery Posts" | Posts as gallery items via the regular Query Loop / Post Template / Featured Image blocks. | **Presets.** Each preset shows a small preview. The filter's Presets panel (Compact chips, Tabs, Segmented control, Soft tags, Minimal links, Theme buttons, Theme links, Pills + mobile dropdown, Dropdown) and the gallery's Captions panel (No captions, Theme caption, Card, Gradient overlay, Hover reveal, Solid bar, Frosted glass, Clean text) apply a complete look in one click. They only set regular attributes, so every value stays editable. **Captions.** Position (hidden by default / below / on the image / on hover), look (plain or gradient / solid / frosted glass / minimal), alignment, size XS–L, text and background color. They apply to image captions and to post titles and excerpts alike. **Videos.** A video item is an Image block (its poster) with a video link, so it filters, lays out and zooms like any photo. Supported: Media Library files (and any .mp4/.webm/.mov URL), YouTube (also Shorts), Vimeo (also unlisted), TikTok and Instagram. *Add content → Videos* (or "Add videos" in an empty gallery) takes a link or Media Library videos: provider thumbnails are saved to the Media Library as posters (Instagram shares none, so its poster is picked by hand), and Media Library videos use their cover image or a frame captured in the editor. An image's **Video** sidebar panel sets or removes the link, or swaps in the video's own thumbnail. On the front end a play badge marks video items; resting the mouse on one plays a muted, looped preview over the poster (not on touch, with reduced motion or Save-Data; turn it off with **Play videos on hover**), and a click opens the player in the lightbox after the zoom lands. Players come from privacy-friendly domains where there is one (`youtube-nocookie.com`, Vimeo with `dnt=1`). The link is kept in the block comment only, so the saved markup is core's own. Gallery items are **ordinary core blocks** (Image, Query Loop, Post Featured Image, Post Title), so their own settings keep working. Images, posts and media-query results can be mixed in one gallery: on the front end the groups dissolve (`display: contents`) into one shared grid. **Gallery Categories** (`gallery_z_category`) is a public taxonomy shared by media, posts and pages (archives at `/gallery-z-category//`, usable in the Query Loop's taxonomy filter). Image blocks inside a gallery get a "Gallery categories" sidebar field that saves straight to the attachment. A gallery can filter by any other taxonomy too. ### Editing - **Edit / Preview** (gallery toolbar). *Edit* shows any layout as a plain grid of whole photos in their order, each with a badge of its categories ("No category" in yellow), and an "Add images" tile at the end. *Preview* is the real layout, and every gallery opens there. In Preview the first click on a gallery selects the gallery itself (a layer over the photos takes it); once it is selected, a click selects a photo. The mode is editor-only and never saved. - **Filter preview:** clicking a Gallery Filter button in the editor filters the galleries in Preview mode, so the categories can be checked before publishing. Nothing is saved. - **Categories for several images at once:** select one image, or shift-click several, and use the tag button in the block toolbar. Each category is a checkbox (mixed when only some of the images have it), and new categories can be created right there. Changes are saved to the images in the Media Library at once. A single image also has the "Gallery categories" sidebar panel. - **Sort** (gallery toolbar): newest or oldest first, title A–Z or Z–A, file name, reverse, shuffle. Posts and media queries keep their places. - **Add content:** "Add images" (multi-select from the Media Library), posts or pages (each item links to its page), a media query. The empty gallery offers the same. - Scroll reveal plays in Preview mode; autoplay and hover effects don't run in the editor. - **Transforms** (block toolbar → Transform to): core Gallery → Filterable Gallery (images keep captions and links; cropped galleries become a grid, uncropped ones masonry; core's image lightbox turns the gallery lightbox on), several selected Image blocks or a Query Loop → Filterable Gallery, Filterable Gallery → core Gallery (when it holds only images), and Ungroup. - **Block icons:** Filterable Gallery, Gallery Filter, Gallery Media Query and the Gallery Posts variation share one icon family (tiles with a turquoise mark), so they are easy to spot in the inserter, toolbar and list view. - **Commands** (command palette, Cmd/Ctrl+K): *Add filterable gallery* inserts a Gallery Filter and a Filterable Gallery that are already connected; *Edit all galleries* / *Preview all galleries* switch every gallery on the page; *Tag selected images* opens the categories menu for the selected images (shown only while images in a gallery are selected). ### WordPress integration - **Importers** (Tools → Gallery Z import, or WP-CLI) for **Envira Gallery, NextGEN Gallery, Modula and FooGallery** (tested with Envira Gallery Lite 1.16, NextGEN 4.5, Modula 3.0 and FooGallery 3.3). Their data is read straight from the database, so the source plugin doesn't need to be active. Each gallery becomes a draft page " (imported)" with a Gallery Filter (when the images have tags) and a Filterable Gallery of core Image blocks, in the source's image order (FooGallery's sort setting and NextGEN's sort order included; excluded NextGEN images are left out). Carried over: alt text and captions (Modula's classic editor and FooGallery keep them on the attachment; NextGEN's escaped HTML becomes plain text), per-image links and new tab, columns, row height, spacing, the tile ratio of cropped grids, and what a click does (lightbox, image file or nothing). When some images have their own link, the gallery uses links and the others open their image file, since a gallery has one click behavior. Layouts: - Envira: automatic → justified rows; columns → masonry, or a grid when cropped to the default size. - Modula: Masonry (`grid`), Creative, Custom grid, Polaroid → masonry; Justified (or `grid` with automatic columns) → rows; Uniform/Fit grid → grid; Slider → carousel. - FooGallery: Masonry → masonry; Justified → rows; Carousel and Image Viewer → carousel; others → grid. - NextGEN: a grid with the Basic Thumbnails columns and thumbnail ratio. Tags and filters (`envira-tag`, `ngg_tag`, Modula filters, FooGallery tags and categories; all but NextGEN's are Pro features) become Gallery Categories on the images; existing ones are reused by name. NextGEN files are copied into the Media Library once (also those NextGEN itself imported from the Media Library, which keeps no link to the original). Re-running skips imported galleries (`_gallery_z_imported_from` on the page, e.g. `envira:123`); re-import updates the page and reuses the copied files. ```bash wp gallery-z import list wp gallery-z import <envira|nextgen|modula|foogallery|all> [--ids=1,2] [--force] [--dry-run] ``` **Replacement shortcodes** (option on the import page, off by default) keep old posts working: `[envira-gallery]`, `[modula]`, `[foogallery]`, `[ngg src="galleries"]` (or `gallery_ids`/`galleries`), `[ngg_images]` and `[nggallery]`, and the Envira, Modula and FooGallery blocks render the imported gallery, even while the old plugin is still active. What was not imported (like NextGEN albums, tag galleries and saved displays `[ngg id="…"]`) keeps the old plugin's output while it is active and renders nothing once it is deactivated. With the option off and the old plugin deactivated, its shortcodes show as text and its blocks render nothing. Not carried over: NextGEN albums and per-shortcode display settings, sliders' and lightboxes' own options, pagination, hover effects and caption visibility (captions show in the lightbox), FooGallery's Pro datasources. - **Media Library.** List view: a Gallery Categories column (terms link to the filtered list), a category filter dropdown, and bulk actions *Add to gallery category…* / *Remove from gallery category…* with a category picker next to them. Grid view: a category filter. Attachment details (media modal): categories as a checklist instead of core's comma-separated slugs. - **Abilities API** (WordPress 6.9+; skipped on older versions), so AI agents and MCP clients can work with galleries. Category `gallery-z`, all shown in REST (`/wp-abilities/v1/abilities`): | Ability | Input | Permission | | --- | --- | --- | | `gallery-z/list-categories` (read-only) | – | `upload_files` | | `gallery-z/find-images` (read-only) | `category`, `search`, `untagged`, `limit` (≤ 500, default 50) | `upload_files` | | `gallery-z/tag-images` | `attachment_ids`, `categories` (names or slugs, created if missing), `mode` add / remove / replace | `upload_files`, `assign_terms`, `edit_post` per image | | `gallery-z/create-gallery` | `title`, `attachment_ids` or `category`, `layout`, `filter`, `columns`, `status` draft / publish | `edit_pages` (+ `publish_pages`) | Over REST, core picks the method from the annotations: GET for the read-only ones, DELETE for `tag-images` (destructive and idempotent), POST for `create-gallery`. - **Patterns** (inserter → Patterns → Galleries): Filterable portfolio (posts), Photo portfolio (filter chips + masonry of your photos), Travel journal (justified rows, quote, carousel), Food menu (square dishes by course with theme links), Team (portraits by department), Hero carousel (full width, autoplay), Latest posts carousel. Patterns that show photos use a Gallery Media Query, so they fill with the site's own images; set its categories afterwards. - **Category archive template.** Block themes get a "Gallery Category Archive" template (`gallery-z//taxonomy-gallery_z_category`) for `/gallery-z-category/<slug>/`: the title, the term description, and one masonry gallery with a lightbox that holds the category's images (Media Query with *Use the archive's category*) and its posts (Query Loop inheriting the archive query). Edit it in Appearance → Editor → Templates; a theme's own `taxonomy-gallery_z_category` template wins. Needs WordPress 6.7+ (`register_block_template`). - **Live preview.** `assets/blueprints/blueprint.json` is the WordPress Playground blueprint for the "Live Preview" button on wordpress.org: installs the plugin, imports 12 Pexels photos in 4 categories and opens a demo page with a filter, masonry and a carousel. It is generated from `bin/playground-demo.php` by `npm run blueprint`; `node bin/blueprint.mjs --local <zip url> <out.json>` writes a variant that installs a local zip, for testing with `npx @wp-playground/cli server --blueprint=<out.json>`. wordpress.org reads it from the SVN `assets/blueprints/` folder, not from the plugin zip. - **Translations.** Text domain `gallery-z`, with a bundled German translation (`languages/gallery-z-de_DE.*`: `.po`/`.mo`/`.l10n.php` for PHP and the front end's lightbox and filter labels, JSON files for the editor scripts) and `languages/gallery-z.pot` as the template. Files in `wp-content/languages/plugins/` win over the bundled ones, for PHP and the editor scripts alike, so language packs from translate.wordpress.org and translations saved by Loco Translate (in its "System" location) override them. Texts typed into a block stay as typed: the filter's "All" button label (edit it right on the button) and its dropdown's screen-reader label only fall back to the translated "All" / "Filter gallery" while empty. ### All options #### Filterable Gallery (`gallery-z/gallery`) | Panel | Option | Values (default first) | | --- | --- | --- | | Layout | Layout | masonry, rows, grid, carousel, accordion (picker with diagrams). Picking the carousel sets slide height 400 / 320 / 260 px and gap 12px while those are untouched | | | Columns | desktop 3, tablet 2, mobile 1 | | | Row height | 240 / 200 / 160 px: row, tile, slide or strip height depending on the layout | | | Row size (grid) | aspect ratio, fixed height | | | Aspect ratio (grid) | 1; tablet/mobile "same as larger screens" or own | | Layout (carousel) | Autoplay | 2 s; 0 = off, 0.5–10 s; pauses on hover, focus, off screen; off with reduced motion | | | Move per click | 1 photo; page, 2, 3 | | | At the end | loop (endless both ways: copies of the photos, about two screens each side, go before and after them, and the row jumps back by one round while nothing on screen changes, so no move meets an end or an unloaded photo; the copies are `aria-hidden`, unfocusable and a click on one opens the real photo's lightbox. If every photo fits on screen it rewinds instead); stop; rewind to the start | | | Slides visible | 0 = photo widths, 1–6 equal slides (tablet ≤ 2, phone 1) | | | Center the current slide | on; slides snap to the middle, the ones beside it fade back (scroll-driven, no JS). Works with every end mode; "Page" moves one slide | | | Show scrollbar | off | | Navigation (carousel) | Arrows | on the photos (default), below the photos, follow the mouse (left/right third; touch swipes), none. Arrow keys, swiping and dragging always work | | | Arrow icon | chevron, thin chevron, bold chevron, arrow, triangle; the lightbox uses the same one (picked in the Lightbox panel for other layouts) | | | Shape, look, size | circle / rounded / square; frosted (default on the photos), solid, outline, plain (white with a soft shadow on the photos); S / M / L | | | Colors | icon, background, border (override the look). Galleries saved with the old single "Arrows" style keep their look | | Layout (accordion) | Open a slice on | click (a click on the open slice runs the click behavior), hover | | Items | Click behavior | link, lightbox, media file, none | | | Open in new tab | off (link and media file) | | | Hover effect | zoom (default), none, lift, color on hover (grayscale), dim others | | | Reveal on scroll | off; rise, fade, zoom, blur, tilt up, wipe, pop, flip, slide, iris (masonry, rows, grid, carousel). CSS scroll-driven animations, no JS | | | Stagger | 2.5 (0–6, step 0.5): scroll distance between neighbors in rem; 0 brings a row in together | | Lightbox | Style | dark, light, frosted (blurred page behind) | | | Opening animation | zoom from thumbnail, fade, none | | | Captions, image counter | on, on | | | Colors | background, text and icons, buttons (prev / next / close) | | | Arrow icon | as in Navigation (layouts without carousel arrows) | | Captions | Presets | No captions, Theme caption, Card, Gradient overlay, Hover reveal, Solid bar, Frosted glass, Clean text | | | Position | hidden (default), below, on the image, on hover | | | Look | plain (gradient on images), solid, frosted glass, minimal | | | Alignment, size | start / center / end; XS, S, M, L | | | Colors | text, background | | Filtering | Filter animation | move + fade, crossfade, slide, zoom, none | | | Gallery ID | for filter blocks to target | | | Filter by | Gallery Categories or any public taxonomy | | Block supports | | wide / full alignment, anchor, text and background color, gap (row and column), corner radius | #### Gallery Filter (`gallery-z/filter`) | Panel | Option | Values (default first) | | --- | --- | --- | | Presets | | Compact chips, Tabs, Segmented control, Soft tags, Minimal links, Theme buttons, Theme links, Pills + dropdown on mobile, Dropdown | | Styles | | Theme button, Theme link, Soft, Pills, Segmented, Underline | | Appearance | Display as | buttons, dropdown on mobile, dropdown | | | Button size | small, XS, M, L, theme | | | Dropdown label | text | | Settings | Gallery | one gallery by ID, or all on the page | | | Taxonomy, categories | which terms to show and in which order | | | "All" button, label | on, "All" | | | Counts | off; inline, badge, superscript; number and badge colors | | | Hide empty, multi-select | on, off | | | URL parameter | e.g. `category` → `?category=food`, rendered server-side | | Block supports | | alignment, layout (justification, orientation, wrap), gap, text / background / button colors, typography, border, shadow | #### Gallery Media Query (`gallery-z/media-query`) Categories, or *Use the archive's category* (on a Gallery Category archive, that category and its children), number of images (24), order by date / title / random, ascending / descending, image size, link to none / file / attachment page, captions. ### Performance Measured by `tests/e2e/performance.spec.js` on the 100-photo sample page (logged out, fast 4G; phone with 4× CPU slowdown): | | LCP | CLS | INP (filter click) | Images on first view | | --- | --- | --- | --- | --- | | Phone 390px | ~260–310 ms | 0.014 (theme font swap) | ~65 ms | 18 requests, 254 KB | | Desktop 1440px | ~360 ms | 0.001 | ~55 ms | 20 requests, 910 KB | **Only what a page uses loads** (sizes gzipped): | Part | Size | Loads | | --- | --- | --- | | `view.js` (filter, gallery core) | 3.1 KB | on pages with a gallery or filter | | `layout.js` (masonry and rows placement) | 1.8 KB | when such a gallery is on the page; never for grid, carousel, accordion (pure CSS) | | `layouts.js` (carousel navigation and loop, click accordion) | 3.5 KB | when a carousel or accordion is on the page | | `lightbox.js` | 2.9 KB | when a lightbox gallery first gets the pointer, focus or a touch (or on the first click); never during the page load | | `video.js` (hover previews, players) | 1.5 KB | when a gallery with videos first gets the pointer, focus or a touch; no video file, provider script or iframe loads before a visitor hovers or clicks | | masonry pre-paint script | 1.0 KB | inline, once, only with masonry or rows | | Base CSS | 2.3 KB | where a gallery renders (in every theme, not site-wide) | | Carousel / accordion / arrows / reveal / lightbox CSS | 0.5–1.1 KB each | only where a gallery uses it | The stylesheets are enqueued from the blocks' render callbacks: into the `<head>` on block themes (WordPress may inline them), as a `<link>` right before the block on classic themes, so nothing renders unstyled. A theme that switches layouts or options on the fly can enqueue the other parts itself: `gallery-z-carousel`, `gallery-z-accordion`, `gallery-z-nav`, `gallery-z-reveal`, `gallery-z-lightbox`. - **Above the fold:** the first desktop row of the page's first gallery loads eagerly, its first image with `fetchpriority="high"`; everything else is `loading="lazy"` with `sizes="auto"`. Tune with the `gallery_z_eager_items` filter. - **Right-sized files:** every image gets a `sizes` value from the gallery's columns, alignment and the theme's content/wide size (row height × aspect ratio for rows), plus an extra 480px image size (`gallery_z_image_size_width`) between WordPress' 300px and 768px ones. - **No layout shift:** images carry width/height; justified rows and grids are pure CSS; masonry and rows are placed by a 1 KB script right after the gallery, before the first paint (inline in the head on block themes, a small file before the gallery on classic themes; CSP nonces supported via `wp_get_inline_script_tag`). - **Little work at runtime:** the layout engine reuses the pre-paint placement and lays out again only when something it depends on changed (gallery width; for masonry an item whose height no longer fits its rows). Rows ignore item resizes, and hover classes never trigger a layout. Carousel autoplay pauses off screen. - **Interaction:** filtering only snapshots items that are on screen before or after the change; the rest just switch. The lightbox is created on first use. - **No virtualization, on purpose:** 100 or even several hundred items are cheap DOM when offscreen images are lazy; keeping them in the page preserves find-in-page, SEO, accessibility and correct filter counts. - Tip: serving WebP/AVIF sub-sizes (WordPress' `image_editor_output_format` filter or the Performance Lab plugin) saves another 30-50% of image bytes. ### How it works - **Server rendering.** `includes/class-items.php` hooks `render_block_data` / `render_block` and decorates each item's opening tag while a gallery renders: `data-gallery-z-terms`, `--gallery-z-ar` for the rows layout, lightbox data, and the click behavior for image links. It uses `WP_HTML_Tag_Processor`. - **Front end.** One Interactivity API module (`src/view/`, ~7 KB minified, no dependencies) shared by gallery and filter. Filtering toggles a class on items inside a View Transition, so items move to their new places; browsers without View Transitions switch instantly. The lightbox is a native `<dialog>` created on first use; a click on the photo or around it closes it, and the page behind doesn't scroll while it's open. Hover captions and effects show on hover and on keyboard focus (`:focus-visible`), so they don't stick after a click. The frosted-glass caption's corners follow the photo's radius minus the caption's inset. - **Layouts are CSS.** Rows = flexbox with `flex-grow` proportional to the aspect ratio. Grid = CSS grid + `aspect-ratio`/`object-fit`. Masonry = CSS grid with 1px rows; `src/shared/layout.js` puts each item in the shortest column (skipped where the browser has native masonry: `display: grid-lanes`, Safari 26.4+, or the older `grid-template-rows: masonry`). Responsive values are custom properties that fall back mobile → tablet → desktop. - **Progressive enhancement.** Without JS every item shows and links work (lightbox links point to the image file). `@starting-style`, View Transitions, `color-mix()`, `backdrop-filter` and `:has()` only add polish.