Skip to content

Instantly share code, notes, and snippets.

@webmandesign
Last active February 6, 2021 03:10
Show Gist options
  • Save webmandesign/011b8ecbf6cb299acb93d574b52c9f17 to your computer and use it in GitHub Desktop.
Save webmandesign/011b8ecbf6cb299acb93d574b52c9f17 to your computer and use it in GitHub Desktop.
Wrapping post content in section divs similar to Medium.com. Section split occurs on Gutenberg wide and full aligned blocks.
<?php
/**
* Creates section divs in the content area.
*
* This is a front-end solution only.
* Splits content into section containers, similar to Medium.com.
* Section split occurs on Gutenberg wide and full aligned blocks.
*
* Copy this function into your WordPress theme's `functions.php` file
* and change the `themeprefix` accordingly.
*
* @link https://codepen.io/webmandesign/post/gutenberg-full-width-alignment-in-wordpress-themes
*
* @param string $content Post content.
*/
function themeprefix_content_sections( $content = '' ) {
// Creating the initial section first.
$content = '<div class="content-section">' . $content . '</div>';
// Requirements check
if ( ! is_callable( 'has_blocks' ) || ! has_blocks( $content ) ) {
return $content;
}
// Vars
$current_block = '';
$content_lines = explode( PHP_EOL, $content );
$alignments = (array) apply_filters( 'themeprefix_content_sections/alignments', array( 'full', 'wide' ) );
// Processing
foreach ( $content_lines as $line_number => $line_content ) {
if ( false === strpos( $line_content, '<!-- wp:' ) && false === strpos( $line_content, '<!-- /wp:' ) ) {
// No block definition HTML comment? Do not process this line.
continue;
}
// Allow bypassing the line with a filter hook.
$line_content_pre = apply_filters( 'themeprefix_content_sections/line_content_pre', false, $line_content, $line_number );
if ( is_string( $line_content_pre ) ) {
$content_lines[ $line_number ] = $line_content_pre;
continue;
}
// Get alignment if set.
preg_match( '/"align":"([^"]*)"/i', $line_content, $alignment );
if ( isset( $alignment[1] ) ) {
$alignment = $alignment[1];
} else {
$alignment = '';
}
if ( in_array( $alignment, $alignments ) ) {
/**
* Found a block with desired alignment definition?
* Do this:
* - get and remember block name/key in $current_block variable,
* - set a wrapper CSS class,
* - open our wrapper div.
*/
preg_match( '/wp:(\S+)/', $line_content, $current_block );
if ( isset( $current_block[1] ) ) {
$current_block = $current_block[1];
$class = sprintf(
(string) apply_filters( 'themeprefix_content_sections/class', 'align-wrap align-wrap-%s', $current_block, $alignment ),
sanitize_title( $alignment )
);
$line_content = str_replace(
'<!-- wp:',
'</div>' . PHP_EOL . '<div class="' . esc_attr( $class ) . '">' . PHP_EOL . '<!-- wp:',
$line_content
);
} else {
$current_block = '';
}
} elseif ( ! empty( $current_block ) && false !== strpos( $line_content, '<!-- /wp:' . $current_block . ' -->' ) ) {
/**
* Have a block name/key saved and found a closing comment for that block?
* Do this:
* - close our wrapper div,
* - reset the $current_block variable.
*/
$line_content = str_replace(
'<!-- /wp:' . $current_block . ' -->',
'<!-- /wp:' . $block . ' -->' . PHP_EOL . '</div>' . PHP_EOL . '<div class="content-section">',
$line_content
);
$current_block = '';
}
// Replace original line content with modified one.
$content_lines[ $line_number ] = $line_content;
}
// Putting the content back together.
$content = implode( PHP_EOL, $content_lines );
// Removing empty section leftovers.
$content = preg_replace(
'/<div class=\"content\-section\">(\s|\n)*<\/div>/',
'',
$content
);
// Output
return $content;
} // /themeprefix_content_sections
// Hook before the `do_blocks` is hooked!
add_filter( 'the_content', 'themeprefix_content_sections', 8 );
@webmandesign
Copy link
Author

Creates section divs in the content area

This is a front-end solution only. Splits content into section containers, similar to Medium.com. Section split occurs on Gutenberg wide and full aligned blocks.

Default functionality

By default the code:

  • Works with full and wide aligned blocks only. This can be modified using themeprefix_content_sections/alignments filter hook, though.
  • Wraps content in additional div.content-section.content-section-align-$alignment divs, where $alignment could be of full or wide value. The class can be modified using themeprefix_content_sections/class filter hook.

Benefits

This should allow using advantages of both styling options of:

Code example

Basically, produces this HTML:

// Example of content with no full/wide aligned blocks:
<div class="our-content-container-example">
	<div class="content-section">
		All content HTML here...
	</div>
</div>

// Example of content with 1 full aligned block:
<div class="our-content-container-example">
	<div class="content-section">
		Content HTML before the full-aligned block here...
	</div>
	<div class="content-section content-section-align-full">
		Full aligned block HTML ...
	</div>
	<div class="content-section">
		Content HTML after the full-aligned block here...
	</div>
</div>

Which could be styled like so:

.content-section {
	max-width: 800px;
	padding: 0 40px;
	margin: 0 auto;
}

.content-section-align-wide,
.content-section-align-full {
	max-width: none;
	padding: 0;
}

.content-section-align-wide {
	max-width: 1200px;
}

How to apply?

Copy this PHP function into your WordPress theme's functions.php file and change the themeprefix appropriately.


Created by Oliver at WebManDesign.eu | Licensed under the terms of GPL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment