Desarrollo de elementos generales
Header
Elementos del Header:
- Logo.
- Menú.
- Sticky Menu (solo se va a mostrar si la resolución no es mobile, y solo cuando se hace un scroll up si la página tiene una gran altura y no se está mostrando el menú principal).
El código principal se tiene que realizar en header.php:
/**
* The header for our theme
*
* This is the template that displays all of the <head> section and everything up until <div id="content">
*
* @link https://developer.wordpress.org/themes/basics/template-files/#template-partials
*
* @package lookalive
*/
require_once('mainmenu.php');
?>
Lo primero que se puede observar es que se requiere el archivo mainmenu.php. Para realizar menús de WordPress es necesario implementar una clase de tipo Walker. Específicamente, hay que extender la clase Walker_Nav_Menu. Este archivo realiza la implementación que vamos a utilizar para el main menu (y para el sticky menu). Veamos el código de mainmenu.php:
class Walker_Main_Menu extends Walker_Nav_Menu {
/**
* At the start of each element, output a <li> and <a> tag structure.
*
* Note: Menu objects include url and title properties, so we will use those.
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$output .= sprintf( "\n<li class='nav-item'><a class='nav-link px-2 mx-1' href='%s'%s>%s</a></li>\n",
$item->url,
( $item->object_id === get_the_ID() ) ? ' class="current"' : '',
$item->title
);
}
}
En la función start_el estamos devolviendo el html de cada opción del menú. Aún no dice nada acerca de la configuración general del menú porque eso se hace por fuera. Siguiendo con header.php:
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="profile" href="https://gmpg.org/xfn/11">
<?php wp_head(); ?>
</head>
En el segmento anterior, devolvemos una serie de configuraciones generales de HTML y traemos el head o metadata de la base de datos de WordPress usando el hook wp_head. Aún no se ha mostrado nada visual. Sin embargo, ya hay bastantes procesos corriendo en el servidor. Por ejemplo, en el head de HTML se definen los archivos de estilos css, y en muchos casos también los de JavaScript. Para poder utilizar nuestros estilos, tenemos que decirle de alguna manera a la función wp_head donde están los archivos.
La forma técnica en que un theme (o un plugin), extiende o implementa funciones de WordPress (como wp_head) es agregando un filtro o una acción. Por ejemplo, si yo quisiera que WordPress hiciera algo especial al guardar la edición de un post tendría que implementar la acción save_post con un método. Si el nombre del método fuera methodX, entonces la linea de código se vería así:
Para la implementación de acciones y filtros en un theme de WordPress, se recomienda usar un archivo llamado functions.php. Para indicar los archivos de estilos y scripts, lo mejor es usar el hook wp_enqueue_scripts. Así es el método que usamos en nuestro functions.php:
wp_enqueue_style( 'lookalive-style', get_stylesheet_uri(), array(), '20190514');
wp_enqueue_style( 'bootstrap', get_template_directory_uri() . '/css/bootstrap.min.css');
wp_enqueue_style( 'roboto-font', 'https://fonts.googleapis.com/css?family=Roboto');
wp_enqueue_script( 'tether', get_template_directory_uri() . '/js/tether.min.js', array(), '20151215', true );
wp_enqueue_script( 'bootstrap-js', get_template_directory_uri() . '/js/bootstrap.min.js', array(), '20151215', true );
wp_enqueue_script( 'lookalive-navigation', get_template_directory_uri() . '/js/navigation.js', array(), '20151215', true );
wp_enqueue_script( 'lookalive-skip-link-focus-fix', get_template_directory_uri() . '/js/skip-link-focus-fix.js', array(), '20151215', true );
wp_enqueue_script( 'lookalive-custom-scripts', get_template_directory_uri() . '/js/scripts.js', array(), '20190429', true );
if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
wp_enqueue_script( 'comment-reply' );
}
}
add_action( 'wp_enqueue_scripts', 'lookalive_scripts' );
Varios de los setups ya venían de underscores. Pero, además hubo que agregar la URL de nuestra tipografía, algunos archivos de Bootstrap y nuestro javascript custom.
Continuando con header.php:
<div class="container-fluid">
Estas dos lineas hacen dos definiciones extremadamente importantes:
- Agrego la tipografía predeterminada a la página usando la función de WordPress body_class.
- Defino el contenedor de Bootstrap para toda la página.
La función body_class es un filtro de WordPress que se usa para agregarle clases css a la página. La idea de los filtros es la misma que con las acciones. La diferencia principal es que los filtros son usados para modificar variables (en este caso body_class). A diferencia de las acciones, los filtros deben retornar un valor (sería el valor de entrada modificado por nuestro filtro). En este caso, nos interesa agregar la tipografía Roboto como predeterminada para la página, y lo vamos a hacer de la siguiente forma:
function custom_class( $classes ) {
$classes[] = 'sansserif-robotofont';
return $classes;
}
En esta función, estamos agregando al arreglo classes una clase css llamada sansserif-robotofont. La misma, se encuentra definida en nuestra hoja de estilos:
font-family: 'Roboto', sans-serif;
}
Siguiendo con header.php, lo primero que hay que definir es el sticky menu:
<div class="col-md-12">
<?php
$items_wrap = '<ul id="%1$s" class="%2$s" style="display:none">%3$s';
$items_wrap .= sprintf( "\n<li class='nav-item ml-md-auto'><a class='nav-link px-2 mx-1' href='javascript:scrollToTop()'><b>Tope ↑</b></a></li>\n</ul>");
wp_nav_menu( array( 'menu' => 'Main Menu',
'walker' => new Walker_Main_Menu(),
'menu_class' => 'nav list-inline nav-mainmenu sticky',
'container' => '',
'items_wrap' => $items_wrap) ); ?>
</div>
</div>
En este segmento:
- Definimos una fila con una columna de ancho 100%.
- Wrapeamos el menú: al principio con la configuración gral del menú asegurándonos de que en principio no se muestre (usando el display:none), y al final con la opción para hacer scroll al tope.
- Configuramos las clases del menú como “nav list-inline nav-mainmenu sticky“. Las primeras son clases Bootstrap, la última nuestra clase para hacer que se comporte como sticky menu.
Luego definimos el espacio para el logo:
<div class="col-md-12">
<a href="/"><img class="my-4 mx-auto d-block" alt="Look Alive" src="<?php echo( get_header_image() ); ?>"></a>
</div>
</div>
El header image se define en la sección de apariencia de WordPress. Para terminar con header.php, vamos a definir el main menu en sí:
<div class="col-md-12">
<nav class="navbar navbar-toggleable navbar-light py-0">
<button class="navbar-toggler mx-auto" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<?php wp_nav_menu( array( 'menu' => 'Main Menu',
'walker' => new Walker_Main_Menu(),
'menu_class' => 'nav navbar-nav navbar-center list-inline mx-auto justify-content-center separator nav-mainmenu',
'container' => '') ); ?>
</div>
</nav>
</div>
</div>
Algunas cosas más parecen ocurrir aquí. Hay un nav declarado así como un botón. Eso es porque se estamos aprovechando algunas de las facilidades de Bootstrap para menús responsive. Cuando el tamaño de la pantalla donde se despliega el sitio sea demasiado angosto, se va a mostrar un botón que abrirá el menú verticalmente con las opciones centralizadas. Es uno de los trucos avanzados que descubrí en la biblioteca luego de empezar de ver que no se veía bien el menú en dispositivos mobile.
Footer
Dado que el footer solo despliega el aviso del Copyright, el código es considerablemente más sencillo:
/**
* The template for displaying the footer
*
* Contains the closing of the #content div and all content after.
*
* @link https://developer.wordpress.org/themes/basics/template-files/#template-partials
*
* @package lookalive
*/
?>
<div class="row bottom-line my-4">
<div class="col-md-12 text-center">
<p style="font-family: Georgia,Times,'Times New Roman',serif;font-size:24px;"><b>© 2019 Maximiliano Goffman</b></p>
</div>
</div>
</div><!-- #content -->
<footer id="colophon" class="site-footer">
</footer><!-- #colophon -->
</div><!-- #page -->
De hecho, borré parte del código que venía con underscores. Aunque hardcodear el texto en el código no sea la mejor práctica, no me parece que sea tan grave siendo un texto estático.
Sidebars
El sidebar va a ser opcional. De hecho voy a definir tres áreas posibles. Si el widget area tiene elementos, entonces se va a mostrar sino no. Defino las áreas en el functions.php:
register_sidebar( array(
'name' => __( 'Before Main Area', 'lookalive' ),
'id' => 'before-main-widget-area',
'description' => __( 'Add widgets here.', 'lookalive' ),
'before_widget' => '
', 'after_widget' => '
', 'before_title' => ' <h2 class="widget-title">', 'after_title' => '</h2> ', ) );
register_sidebar( array(
'name' => __( 'After Main Area', 'lookalive' ),
'id' => 'after-main-widget-area',
'description' => __( 'Add widgets here.', 'lookalive' ),
'before_widget' => '
', 'after_widget' => '
', 'before_title' => ' <h2 class="widget-title">', 'after_title' => '</h2> ', ) );
register_sidebar( array(
'name' => __( 'Left Sidebar Area', 'lookalive' ),
'id' => 'left-sidebar-widget-area',
'description' => __( 'Add widgets here.', 'lookalive' ),
'before_widget' => '
', 'after_widget' => '
', 'before_title' => ' <h2 class="widget-title">', 'after_title' => '</h2> ', ) );
}
add_action( 'widgets_init', 'add_widgets_init' );
El código que agrega el área es muy sencillo. Por ejemplo, en sidebar.php defino una de ellas:
/**
* The sidebar containing the main widget area
*
* @link https://developer.wordpress.org/themes/basics/template-files/#template-partials
*
* @package lookalive
*/
if ( is_active_sidebar( 'after-main-widget-area' ) ) { ?>
<div class="row bottom-line">
<div class="col-md-12 my-4">
<?php dynamic_sidebar( 'after-main-widget-area' ); ?>
</div>
</div>
<?php } else {return;} ?>
Si el área en específica está activa entonces que devuelva todos los widgets que contiene.