Building Responsive Gutenberg Blocks for Mobile with Vue.js: A Deep Dive

WordPress’s Gutenberg editor has revolutionized content creation, and the ability to build custom blocks extends its power significantly. While creating blocks for desktop is relatively straightforward, ensuring optimal mobile responsiveness requires careful planning and implementation. This blog post will guide you through building responsive Gutenberg blocks using Vue.js, covering everything from setup to advanced techniques for handling different screen sizes.

I. Project Setup & Dependencies:

We’ll leverage the power of @wordpress/scripts for building the block and @vue/cli-service for managing the Vue.js application within the block. First, ensure you have Node.js and npm (or yarn) installed. Then, create a new WordPress plugin directory:

mkdir my-vue-gutenberg-block
cd my-vue-gutenberg-block

Inside, create the following files:

  • gutenberg-block.php (main plugin file)
  • src/ (directory for Vue.js components)
  • src/components/MyVueBlock.vue (our Vue component)
  • webpack.config.js (webpack configuration)

II. The WordPress Plugin File (gutenberg-block.php):

This file registers our block with WordPress. It handles the enqueueing of scripts and styles, as well as the block registration itself.

<?php
/**
 * Plugin Name: My Vue Gutenberg Block
 * Plugin URI:  https://yourwebsite.com/
 * Description: A Gutenberg block built with Vue.js.
 * Version:     1.0.0
 * Author:      Your Name
 * Author URI:  https://yourwebsite.com/
 * License:     GPL2
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: my-vue-gutenberg-block
 */

// Enqueue scripts and styles
function my_vue_gutenberg_block_enqueue_scripts() {
    wp_enqueue_script(
        'my-vue-gutenberg-block-script',
        plugins_url( 'dist/main.js', __FILE__ ),
        array( 'wp-blocks', 'wp-element', 'wp-i18n', 'wp-components' ),
        filemtime( plugin_dir_path( __FILE__ ) . 'dist/main.js' ), // Use filemtime for cache busting
        true
    );
    wp_enqueue_style(
        'my-vue-gutenberg-block-style',
        plugins_url( 'dist/style.css', __FILE__ ),
        array(),
        filemtime( plugin_dir_path( __FILE__ ) . 'dist/style.css' )
    );
}
add_action( 'enqueue_block_editor_assets', 'my_vue_gutenberg_block_enqueue_scripts' );

// Register the block
function my_vue_gutenberg_block_register_block() {
    register_block_type( 'my-plugin/my-vue-block', array(
        'render_callback' => 'my_vue_gutenberg_block_render_callback',
    ) );
}
add_action( 'init', 'my_vue_gutenberg_block_register_block' );

// Render callback (optional, for server-side rendering)
function my_vue_gutenberg_block_render_callback( $attributes ) {
    //  Handle server-side rendering if needed.  For this example, we'll rely on client-side rendering.
    return '';
}
?>

III. The Vue Component (src/components/MyVueBlock.vue):

This is where the magic happens. We’ll build a responsive block that displays a simple title and description, adapting to different screen sizes.

<template>
  <div class="my-vue-block">
    <h2 v-if="title">{{ title }}</h2>
    <p v-if="description">{{ description }}</p>
    <div class="mobile-only" v-if="$vuex.state.isMobile">This content is only visible on mobile!</div>
  </div>
</template>

<script>
import { store } from './store.js'; // Import Vuex store (explained later)

export default {
  name: 'MyVueBlock',
  data() {
    return {
      title: 'My Responsive Block',
      description: 'This block is responsive and adapts to different screen sizes.',
    };
  },
  computed: {
      isMobile: function () {
          return this.$vuex.state.isMobile
      }
  },
  mounted() {
    //Access block attributes from the WordPress editor
      const attributes = wp.data.select('core/block-editor').getBlock(this.$el.id).attributes;
      this.title = attributes.title || this.title;
      this.description = attributes.description || this.description;

    //Detect mobile
    window.addEventListener("resize", this.handleResize);
    this.handleResize()
  },
  beforeDestroy(){
    window.removeEventListener("resize", this.handleResize)
  },
  methods: {
    handleResize(){
        this.$vuex.commit('setIsMobile', window.innerWidth < 768);
    }
  }
};
</script>

<style scoped>
.my-vue-block {
  padding: 20px;
  border: 1px solid #ccc;
  background-color: #f9f9f9;
}

.mobile-only {
    display: none;
}

@media (max-width: 767px) {
    .mobile-only {
        display: block;
    }
}

</style>

IV. Vuex Store (src/components/store.js):

We’ll use Vuex to manage the mobile detection state across the application.

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
    state: {
        isMobile: false,
    },
    mutations: {
        setIsMobile(state, isMobile) {
            state.isMobile = isMobile;
        }
    }
});

V. Main App Entry Point (src/main.js):

This file creates the Vue instance and renders our block component.

import Vue from 'vue';
import App from './components/MyVueBlock.vue';
import { store } from './components/store.js';

new Vue({
  el: '#my-vue-block-app', // This will need to match the ID in your Gutenberg block wrapper
  store,
  render: h => h(App)
});

VI. Webpack Configuration (webpack.config.js):

This configures Webpack to bundle our Vue.js code.

const path = require('path');

module.exports = {
  entry: './src/main.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' also works
    },
    extensions: ['*', '.js', '.vue', '.json']
  },
  mode: 'production' // Use 'development' for debugging
};

VII. Building the Block:

Navigate to your plugin’s directory in the terminal and run:

npm install vue vue-loader vue-template-compiler vuex css-loader vue-style-loader
npx webpack

This will bundle your Vue code into dist/main.js.

VIII. Advanced Techniques for Responsiveness:

  • CSS Frameworks: Consider using a CSS framework like Bootstrap or Tailwind CSS for quicker responsive styling.
  • Vue.js Directives: Use v-show or v-if to conditionally render elements based on screen size.
  • Vue.js Components: Break down your block into smaller, reusable components for better organization and maintainability.
  • Media Queries: Utilize CSS media queries directly within your <style> tag for precise control over layout and styling at different breakpoints.
  • JavaScript-Based Responsive Techniques: Implement JavaScript functions to dynamically adjust content based on screen dimensions. For instance, you could change image sizes or rearrange elements.

IX. Server-Side Rendering (SSR): While client-side rendering (as shown above) is often sufficient, for SEO purposes, server-side rendering can be beneficial. This involves rendering the Vue component on the server and providing the HTML to the browser, although this adds complexity and requires a server-side rendering setup like Next.js or Nuxt.js (beyond the scope of this tutorial).

X. Conclusion:

Building responsive Gutenberg blocks with Vue.js offers a powerful and efficient way to create engaging and user-friendly content for all devices. By combining Vue.js’s component-based architecture with WordPress’s block editor, you can create sophisticated and dynamic blocks that seamlessly adapt to various screen sizes. Remember to thoroughly test your blocks on different devices and screen resolutions to ensure optimal performance and visual appeal. This detailed guide provides a solid foundation for building more complex and feature-rich Gutenberg blocks using Vue.js. Remember to replace placeholders like my-plugin/my-vue-block and adjust paths as needed for your specific project setup.

Leave a Reply

Your email address will not be published. Required fields are marked *

Trending