-
Notifications
You must be signed in to change notification settings - Fork 7
Tutorial on building a "hover reveal" pattern #215
Description
Discussed in #203
Originally posted by justintadlock January 11, 2024
There's been a lot of discussion around building a specific layout with the block editor. Specifically, something like this (shown in a hover card style):
This is a pretty popular web design pattern, and it'd be great to show how it's possible with the block editor and can be shipped in a theme as a pattern.
Some of the community discussion and responses:
- https://www.youtube.com/watch?v=g8YxdSIq-uk
- https://twitter.com/pootlepress/status/1737444341910479103
- https://www.briancoords.com/the-block-editor-is-still-not-a-page-builder/
- https://twitter.com/justintadlock/status/1745212928259690782
Responses to my tweet (last link above) have been overwhelmingly positive and ask for a tutorial. Thus, this proposal.
The Proposal
Write a tutorial that covers a lot of ground that is geared toward theme creators. This would be:
- How to build this layout in the WordPress editor (no custom CSS or plugins necessary!).
- How to ship this layout in a block pattern.
- How to make this pattern even more awesome with custom block styles:
- Add a "hover reveal" block style for the Cover block.
- Add a "flip card" block style for the Cover block (haven't tested this yet but am pretty sure it'll work).
- Add a "grid auto" option for improved Columns block responsiveness.
The Code
I've done some preliminary code work and am just backing it up here. Note: some of the below will have classes and such from my personal theme, so it'll need to be translated to TT4.
assets/css/blocks/core/columns.scss:
// Grid style.
.wp-block-columns-is-layout-flex.is-style-grid-auto {
display: grid !important;
grid-template-columns: repeat( 1, 1fr );
@media ( min-width: 40rem ) {
grid-template-columns: repeat( 2, 1fr );
}
@media ( min-width: 64rem ) {
&:has( > :where(
.wp-block-column:nth-child( 5 ),
.wp-block-column:nth-child( 6 )
) ) {
grid-template-columns: repeat( 3, 1fr );
}
}
@media ( min-width: 80rem ) {
grid-auto-columns: minmax( 0, 1fr );
grid-auto-flow: column;
}
}assets/css/blocks/core/cover.scss:
// Hover reveal block style.
.wp-block-cover.is-style-hover-reveal {
position: relative;
border-radius: var( --wp--custom--defaults--border-radius );
box-shadow: var( --wp--custom--defaults--shadow );
// The cover background (used for the overlay), needs to have its
// opacity set to `1` so that we have a background when the image is
// hidden for the reveal.
.wp-block-cover__background {
transition: opacity 0.5s ease-in-out;
}
// Only set the opacity if we're not hovered/focused.
&:where( :not( :hover, :focus-within ) ) .wp-block-cover__background {
opacity: 1;
}
// By default, we zero out the background image's opacity. Then, we
// reveal it on hover/focus.
.wp-block-cover__image-background {
opacity: 0;
transition: all 0.5s ease-in-out;
}
&:hover,
&:focus-within {
.wp-block-cover__image-background {
opacity: 1;
transform: scale( 1.3 );
}
}
// Remove text decoration for links.
a {
text-decoration: none;
outline: none;
}
// This will technically take all links and position them over the
// entire Cover block container. However, the last link will win out.
// We're also making sure that we don't target this when in the editor.
&:where( :not( [class*=block-editor] ) ) a:after {
content: "";
z-index: 1;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
}
}patterns/hero-cards.php:
<?php
/**
* Title: Hero: Hover Cards
* Slug: x3p0-ideas/hero-hover-cards
* Description: Make a statement.
* Categories: featured
* Keywords: hero, cover, hover, card
* Block Types: core/cover
* Viewport Width: 1376
*/
$url = home_url();
$image = get_theme_file_uri( 'public/media/images/purple-sunset.webp' );
?>
<!-- wp:group {
"align":"full",
"style":{
"spacing":{
"padding":{
"top":"var:preset|spacing|plus-4",
"bottom":"var:preset|spacing|plus-4",
"left":"var:preset|spacing|plus-3",
"right":"var:preset|spacing|plus-3"
},
"blockGap":"var:preset|spacing|plus-4"
}
},
"backgroundColor":"neutral-base",
"layout":{"type":"default"}
} -->
<div class="wp-block-group alignfull has-neutral-base-background-color has-background" style="padding-top:var(--wp--preset--spacing--plus-4);padding-right:var(--wp--preset--spacing--plus-3);padding-bottom:var(--wp--preset--spacing--plus-4);padding-left:var(--wp--preset--spacing--plus-3)">
<!-- wp:group {
"style":{"spacing":{"blockGap":"var:preset|spacing|base"}},
"layout":{"type":"constrained"}
} -->
<div class="wp-block-group">
<!-- wp:group {
"style":{"spacing":{"blockGap":"var:preset|spacing|minus-3"}},
"layout":{"type":"constrained"}
} -->
<div class="wp-block-group">
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center"><?php esc_html_e( 'Placeholder Text', 'x3p0-ideas' ) ?></p>
<!-- /wp:paragraph -->
<!-- wp:heading {"textAlign":"center"} -->
<h2 class="wp-block-heading has-text-align-center"><?php esc_html_e( 'Placeholder Heading', 'x3p0-ideas' ) ?></h2>
<!-- /wp:heading -->
</div>
<!-- /wp:group -->
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center"><?php esc_html_e( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam interdum turpis quis metus aliquam, id pharetra arcu dignissim. Sed in sollicitudin mi.', 'x3p0-ideas' ) ?></p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:columns {"className":"is-style-grid-auto"} -->
<div class="wp-block-columns is-style-grid-auto">
<?php foreach ( range( 1, 4 ) as $column ) : ?>
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:cover {
"url":"<?= esc_url( $image ) ?>",
"id":2329,
"dimRatio":50,
"overlayColor":"contrast",
"isUserOverlayColor":true,
"minHeight":20,
"minHeightUnit":"vh",
"style":{
"spacing":{
"padding":{
"top":"var:preset|spacing|plus-3",
"bottom":"var:preset|spacing|plus-3",
"left":"var:preset|spacing|plus-3",
"right":"var:preset|spacing|plus-3"
}
}
},
"className":"is-style-hover-reveal",
"layout":{"type":"default"}
} -->
<div class="wp-block-cover is-style-hover-reveal" style="padding-top:var(--wp--preset--spacing--plus-3);padding-right:var(--wp--preset--spacing--plus-3);padding-bottom:var(--wp--preset--spacing--plus-3);padding-left:var(--wp--preset--spacing--plus-3);min-height:20vh">
<span aria-hidden="true" class="wp-block-cover__background has-contrast-background-color has-background-dim"></span>
<img class="wp-block-cover__image-background wp-image-2329" alt="" src="<?= esc_url( $image ) ?>" data-object-fit="cover"/>
<div class="wp-block-cover__inner-container">
<!-- wp:group {
"align":"full",
"style":{"dimensions":{"minHeight":"24rem"}},
"layout":{
"type":"flex",
"orientation":"vertical",
"verticalAlignment":"space-between"
}
} -->
<div class="wp-block-group alignfull" style="min-height:24rem">
<!-- wp:group {
"style":{
"spacing":{
"padding":{
"top":"var:preset|spacing|minus-3",
"bottom":"var:preset|spacing|minus-3",
"left":"var:preset|spacing|base",
"right":"var:preset|spacing|base"
}
}
},
"backgroundColor":"primary-contrast",
"layout":{"type":"default"},
"fontSize":"sm"
} -->
<div class="wp-block-group has-primary-contrast-background-color has-background has-sm-font-size" style="padding-top:var(--wp--preset--spacing--minus-3);padding-right:var(--wp--preset--spacing--base);padding-bottom:var(--wp--preset--spacing--minus-3);padding-left:var(--wp--preset--spacing--base)">
<!-- wp:paragraph -->
<p><?php esc_html_e( 'Placeholder', 'x3p0-ideas' ) ?></p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:group {
"style":{
"spacing":{"blockGap":"var:preset|spacing|minus-3"}},
"layout":{"type":"default"}
} -->
<div class="wp-block-group">
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading"><a href="<?= esc_url( $url ) ?>"><?php esc_html_e( 'Placeholder Heading', 'x3p0-ideas' ) ?></a></h3>
<!-- /wp:heading -->
<!-- wp:paragraph {"fontSize":"sm"} -->
<p class="has-sm-font-size"><?php esc_html_e( 'This is placeholder text.', 'x3p0-ideas' ) ?></p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
</div>
</div>
<!-- /wp:cover -->
</div>
<!-- /wp:column -->
<?php endforeach ?>
</div>
<!-- /wp:columns -->
</div>
<!-- /wp:group -->
```</div>Metadata
Metadata
Assignees
Labels
Type
Fields
Give feedbackProjects
Status
