Wordpress

Como crear un theme de WordPress desde 0 – 2021

Como crear un theme de WordPress desde 0 – 2021

Manuales

En este post aprenderás a crear un theme de WordPress desde 0. Para ello, damos por supuesto que tienes conocimientos de HTML, CSS, PHP y algunos más básicos de WordPress, al menos cómo instalarlo y gestionarlo.

Si por el contrario, ya has creado tu theme y sólo buscas un manual de WordPress, puedes ojear el nuestro.

Archivos para tu theme de WordPress

Después de seguir todos estos pasos y recomendaciones, serás capaz de crear un theme de WordPress desde cero. Además, se debe tener en cuenta que antes de todos estos pasos, lo ideal es tener un diseño definido. También preparar los estilos para que tu nuevo theme sea Responsive.

Dónde comprar un theme de WordPress

Existen muchas webs donde comprar un theme de WordPress de calidad, pero si prefieres no gastarte un € en este aspecto también dispones de opciones gratuitas. La pega es que nunca sabes si contienen código malicioso (a no ser que lo revises, fichero a fichero), además de que no suelen contar con soporte técnico ni casi documentación.

Si lo que buscas es algo 100% adaptado a tus necesidades, la mejor opción es pagar a un diseñador y un programador para que creen un theme de WordPress a tu medida. Es la opción más cara, pero normalmente la que mejor funciona.

Y la tercera opción, que es comprar un theme. Hay muchos lugares en internet dónde comprarlo, aquí os listamos algunos de ellos:

1. ThemeForest

themeforest

2. Cyberchimps

cyberchimps

3. Elegant themes

elegantthemes

4. Wpzoom

wpzoom

Estas son sólo algunas de las más famosas. La lista puede aumentar con el paso del tiempo. El siguiente paso es conocer dónde está la documentación básica para crear o modificar un theme de WordPress.

Documentación técnica

El mejor lugar dónde buscar información sobre WordPress es en el codex.wordpress.org. Ahí puedes encontrar información de todo lo relacionado con WordPress. Lo que ahora queremos buscar es documentaciñon relacionada con los themes:

Página principal: http://codex.wordpress.org/Theme_Development
Sobre su estructura:  http://codex.wordpress.org/Theme_Development#Anatomy_of_a_Theme
Sobre sus ficheros: http://codex.wordpress.org/Theme_Development#Template_Files
Sobre header.php: http://codex.wordpress.org/Theme_Development#Document_Head_.28header.php.29
Sobre menús: http://codex.wordpress.org/Theme_Development#Navigation_Menus_.28header.php.29
Sobre sidebar.php: http://codex.wordpress.org/Theme_Development#Widgets_.28sidebar.php.29
Sobre footer.php: http://codex.wordpress.org/Theme_Development#Footer_.28footer.php.29
Sobre index.php: http://codex.wordpress.org/Theme_Development#Index_.28index.php.29
Sobre archive.php: http://codex.wordpress.org/Theme_Development#Archive_.28archive.php.29
Sobre page.php: http://codex.wordpress.org/Theme_Development#Pages_.28page.php.29
Sobre single.php: http://codex.wordpress.org/Theme_Development#Single_Post_.28single.php.29
Sobre comments.php: http://codex.wordpress.org/Theme_Development#Comments_.28comments.php.29
Sobre search.php: http://codex.wordpress.org/Theme_Development#Search_Results_.28search.php.29

Si vas a la principal, tendrás un listado con todos los contenidos. Ya ves que toda la documentación está en inglés, pero aún no dominando el idioma, es fácil de seguir y entender.

Crear theme de WordPress desde cero

Introducción

En este caso, crearemos un theme de WordPress desde cero, que utilizará Boostrap y estará orientado a un blog.

No nos pararemos mucho en la parte visual, ya que al fin y al cabo los estilos son facilmente editables.

Nuestro theme se llamará blog, y lo crearemos paso a paso, mostrando cada parte de código que creemos.

Estructura de ficheros

Seguiremos una estructura de archivos muy básica, pero que siendo simple, nos permitirá crear un theme para un blog de forma 100% funcional. A continuación se muestra la estructura de ficheros y directorios ordenados alfabéticamente.

  • [re-directory]blog
    • [re-directory]template-parts
      • [re-file]content.php
      • [re-file]content-page.php
      • [re-file]content-single.php
      • [re-file]no-content.php
      • [re-file]sidebar.php
    • [re-file]archive.php
    • [re-file]author.php
    • [re-file]category.php
    • [re-file]class-wp-bootstrap-navwalker.php
    • [re-file]comments.php
    • [re-file]footer.php
    • [re-file]functions.php
    • [re-file]header.php
    • [re-file]index.php
    • [re-file]page.php
    • [re-file]screenshot.png
    • [re-file]search.php
    • [re-file]single.php
    • [re-file]style.css
    • [re-file]tag.php

Código de cada archivo

Mostraremos el contenido de cada archivo de nuestro nuevo theme, por orden de importancia para poder entender mejor el contenido y funcionamiento de cada uno de ellos.

index.php

Es el archivo principal del módulo, además de ser utilizado para cargar el listado de últimas entradas.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row mb-5 header-title">
        <div class="col-md-12">
            <h1><?php echo __('Last publications', 'blog'); ?></h1>
            <hr/>
        </div>
    </div>

    <div class="row">
        <div class="col-md-8">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-4 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

style.css

Es el fichero en el que podemos poner las reglas CSS que necesitemos.

En el comentario inicial definiremos el nombre del theme y demás información como la descripción, licencia etc.

/*
 Theme Name: Blog Theme
 Theme URI: https://adaweb.es
 Description: Simple theme based on Boostrap framework
 License: GNU General Public License v2 or later
 License URI: http://www.gnu.org/licenses/gpl-2.0.html
 */
 /* Common  */
 img{
     max-width: 100%;
     height: auto;
 }

screenshot.png

Será una imagen o captura de pantalla que represente a nuestro theme en el listado de WordPress.

functions.php

En el fichero functions.php de nuestro theme es el lugar en que estableceremos funciones o métodos para trabajar con las funcionalidades propias de WordPress, o crea unas nuevas.

El código de este archivo dependerá de nuestras necesidades.

<?php
 /* Registro del menú de WordPress */
 add_theme_support( 'nav-menus' );
 if ( function_exists( 'register_nav_menus' ) ) {
   register_nav_menus(
     array(
       'main' => 'Main',
     )
   );
 }
 /* Sidebar */
 if(function_exists('register_sidebar')){
   register_sidebar(
     array(
       'name' => 'Main Sidebar'
     )
   );
 }
 /* Deshabilita HTML de los comentarios */
 add_filter('pre_comment_content', 'wp_specialchars');
 /* WordPress menu */
 function list_menu($atts, $content = null) {
   extract(
     shortcode_atts(
       array(  
         'menu'            => '', 
         'container'       => 'div', 
         'container_class' => '', 
         'container_id'    => '', 
         'menu_class'      => 'menu', 
         'menu_id'         => '',
         'echo'            => true,
         'fallback_cb'     => 'wp_page_menu',
         'before'          => '',
         'after'           => '',
         'link_before'     => '',
         'link_after'      => '',
         'depth'           => 0,
         'walker'          => '',
         'theme_location'  => ''), 
       $atts
     )
   );
 return wp_nav_menu( array( 
     'menu'            => $menu, 
     'container'       => $container, 
     'container_class' => $container_class, 
     'container_id'    => $container_id, 
     'menu_class'      => $menu_class, 
     'menu_id'         => $menu_id,
     'echo'            => false,
     'fallback_cb'     => $fallback_cb,
     'before'          => $before,
     'after'           => $after,
     'link_before'     => $link_before,
     'link_after'      => $link_after,
     'depth'           => $depth,
     'walker'          => $walker,
     'theme_location'  => $theme_location));
 }
 /* Create the shortcode */
 add_shortcode("listmenu", "list_menu");
 /* Register Custom Navigation Walker */
 function register_navwalker(){
   require_once get_template_directory() . '/class-wp-bootstrap-navwalker.php';
 }
 add_action( 'after_setup_theme', 'register_navwalker' );
 /* Estilos / function blog_enqueue_styles() {     wp_enqueue_style( 'bootstrap', 'https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css');   wp_enqueue_style( 'font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css');   / Last for override Boostrap css rules */
   wp_enqueue_style( 'style', get_stylesheet_uri() );
 }
 add_action('wp_enqueue_scripts', 'blog_enqueue_styles');
 /* Scripts */
 function blog_enqueue_scripts() {
   wp_enqueue_script( 'bootstrap', 'https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js');
 }
 add_action( 'wp_enqueue_scripts', 'blog_enqueue_scripts');
 /* Imagen destacada post */
 add_theme_support('post-thumbnails');
 set_post_thumbnail_size(150, 150, true);

class-wp-bootstrap-navwalker.php

Es una clase que nos ayudará a montar el menú propio de WordPress pero al modo de Boostrap.

El contenido de este archivo no se especificará aquí, ya que es muy largo. Se puede descargar al final de esta publicación, junto con los demás ficheros de este nuevo theme.

header.php

Aquí definiremos el código para la cabecera o header de nuestro theme.

En este fichero, lo que no haremos es cargar hojas de estilos CSS ni scripts JavaScript.

<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
	<meta charset="<?php bloginfo( 'charset' ); ?>">
	<title><?php wp_title(); ?> <?php bloginfo('name'); ?></title>
	<meta name="viewport" content="width=device-width, minimum-scale=1">
	<link rel="shortcut icon" href="<?php bloginfo('stylesheet_directory'); ?>/images/favicon.ico" hreflang="es" />
	<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" hreflang="es" />
	<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
	<div id="top" class="content">
		<header class="mb-5">	
			<div class="container-fluid">
				<div class="row">				
					<nav class="navbar navbar-expand-lg bg-primary" role="navigation">
						<a class="navbar-brand" href="<?php echo get_option('home'); ?>">
							<img class="top-logo" src="<?php echo get_template_directory_uri(); ?>/images/logo.png" alt="<?php bloginfo('name'); ?>"/>
						</a>
						<div class="container">
							<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-controls="bs-example-navbar-collapse-1" aria-expanded="false" aria-label="Toggle navigation">
								<span class="navbar-toggler-icon"></span>
							</button>								
							<?php
							wp_nav_menu( array(
								'theme_location'    => 'main',
								'depth'             => 2,
								'container'         => 'div',
								'container_class'   => 'collapse navbar-collapse',
								'container_id'      => 'top-menu',
								'menu_class'        => 'nav navbar-nav',
								'fallback_cb'       => 'WP_Bootstrap_Navwalker::fallback',
								'walker'            => new WP_Bootstrap_Navwalker(),
							) );
							?>
						</div>
					</nav>					
				</div>
			</div>
		</header>			
	</div>

footer.php

Aquí definiremos el código para el pie de página o footer de nuestro theme.

<footer class="pt-5 pb-5 text-lg-start bg-primary text-white">
	<div class="container-fluid">
		<div class="row">			
			<div class="col-md-12">
				<p class="text-center"><b>Todos los derechos reservados </b> | <small> <?php echo date('Y'); ?></small></p>
			</div>
		</div>
	</div>
</footer>
<?php wp_footer(); ?>
</body>
</html>

page.php

Este fichero es el encargado de representar un tipo de contenido propio de WordPress, la página.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row">
        <div class="col-md-9">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content-page');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-3 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

En esta versión del theme, cargaremos ciertas plantillas con la función get_template_part(). Esto lo haremos para evitar repetir código en varios ficheros.

El código de este fichero es bastante sencillo. Se comprueba si hay contenidos y se muestra. En caso de no haberlo, se carga un mensaje.

Además, se carga el sidebar.

Podremos crear un fichero para una páginaen concreto. Le llamaremos page-5.php, por ejemplo, si el ID de la página es el 5.

single.php

Este fichero es el encargado de representar otro tipo de contenido propio de WordPress, el post.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row">
        <div class="col-md-8">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content-single');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-4 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

Realiza la misma tarea que el anterior, pero en vez de mostrar los datos de una página, lo hace de un post.

El motivo de existir un fichero para cada tipo de contenido es que podemos querer mostrar cosas distintas o de distinta forma según el caso.

Además, podremos crear un fichero para un post en concreto. Le llamaremos single-12.php, por ejemplo, si el ID del post es el 12.

category.php

Es la plantilla que se utiliza para la vista de una categoría. Normalmente, en esta vista se cargan los posts de una determinada categoría.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row mb-5 header-title">
        <div class="col-md-12">
            <h1><?php echo single_cat_title(); ?></h1>
            <p class="lead"><?php echo __( 'This contents are categorized in', 'blog' ) ?> <?php echo single_tag_title(); ?></p>
            <hr/>
        </div>
    </div>

    <div class="row">
        <div class="col-md-8">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-4 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

tag.php

Es la plantilla que se utiliza para la vista de una tag o etiqueta. Normalmente, en esta vista se cargan los posts de una determinada etiqueta.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row mb-5 header-title">
        <div class="col-md-12">
            <h1><?php echo single_tag_title(); ?></h1>
            <p class="lead"><?php echo __( 'This contents are tagged in', 'blog' ) ?> <?php echo single_tag_title(); ?></p>
            <hr/>
        </div>
    </div>

    <div class="row">
        <div class="col-md-8">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-4 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

archive.php

Es la plantilla que se utiliza para mostrar los posts o contenidos publicados en una determinada fecha.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row mb-5 header-title">
        <div class="col-md-12">
            <h1><?php echo the_archive_title(); ?></h1>
            <p class="lead"><?php echo __( 'This contents are posted by', 'blog' ) ?> <?php echo the_archive_title(); ?></p>
            <hr/>
        </div>
    </div>

    <div class="row">
        <div class="col-md-8">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-4 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

author.php

Es la plantilla que se utiliza para mostrar los posts o contenidos publicados por un autor en concreto. En este caso, además de mostrar los posts, vamos a mostrar información del autor.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row mb-5 header-title">
        <div class="col-md-12">
            <h1><?php echo __( 'Posts by author', 'blog' ) ?></h1>
            <p class="lead"><?php echo __( 'This contents are posted by', 'blog' ) ?> <?php echo get_the_author_meta('display_name'); ?></p>
            <hr/>
        </div>
    </div>

    <div class="row mb-5 header-author">
        <div class="col-md-12">            
            <div class="card text-center">
                <div class="card-header">
                    <?php echo get_the_author_meta('display_name'); ?>
                </div>
                <div class="card-body">
                    <?php echo get_avatar( get_the_author_meta('ID')); ?>
                    <h5 class="card-title mt-4"><?php echo get_the_author_meta('user_firstname'); ?> <?php echo get_the_author_meta('user_lastname'); ?></h5>                    
                    <p class="card-text"><?php echo get_the_author_meta('user_description'); ?></p>
                    <p><b><a class="btn btn-success mt-3" href="mailto:<?php echo get_the_author_meta('user_email'); ?>" title="<?php echo __( 'Send mail: ', 'blog' ) ?> <?php echo get_the_author_meta('user_email'); ?>"><?php echo __( 'Contact with', 'blog' ) ?> <?php echo get_the_author_meta('user_firstname'); ?> </a></b></p>
                </div>
            </div>
        </div>
    </div>

    <div class="row">
        <div class="col-md-8">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-4 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

search.php

Es la plantilla que se utiliza para mostrar los resultados de búsqueda de un término.

<?php
get_header(); 
?>
<div id="main" class="container">
    <div class="row mb-5 header-title">
        <div class="col-md-12">
            <h1><?php echo __( 'Results for search ', 'blog' ) ?></h1>
            <p class="lead"><?php echo __( 'Results for search ', 'blog' ) ?> <?php echo $_GET['s']; ?></p>
            <hr/>
        </div>
    </div>

    <div class="row">
        <div class="col-md-8">
            <?php
            if(have_posts()){
                while(have_posts()){
                    the_post(); 
                    get_template_part('template-parts/content');
                }
            }else{
                get_template_part('template-parts/no-content');
            } 
            ?>
        </div>
        <div class="col-md-4 blog-sidebar">
            <?php 
            get_template_part('template-parts/sidebar');
            ?>
        </div>
    </div>
</div>
<?php
get_footer();
?>

comments.php

Es la plantilla que se utiliza para mostrar los comentarios en una página o post.

<?php if ( have_comments() ){ ?>
    <h2 class="comments-title"><?php echo __('Comments', 'blog'); ?></h2>

    <?php
    wp_list_comments( array(
        'style'       => 'div',
        'short_ping'  => true,
        'avatar_size' => 74,
    ) );

   
    if ( !comments_open() && get_comments_number() ) {
      ?>
      <p class="no-comments"><?php echo __( 'Comments are closed.' , 'blog' ); ?></p>
      <?php 
  }
}
comment_form(); 
?>

Utilización

Una vez creado el theme, deberemos situarlo en el directorio /wp-content/themes/ para poder activarlo desde el backend.

Leave a reply