Uso de los pseudoelementos :before y :after de CSS3

¿Cuántas veces has tenido que poner una coletilla al lado de varios elementos en una web? Por ejemplo, poner la palabra «Error» antes de un mensaje de error. ¿No te encantaría que eso pudiera automatizarse?.

Pues con CSS3 puedes hacerlo. Con los pseudoelementos :before y :after. Estos te permiten añadir un contenido html antes (:before) o después (:after) de un elemento desde vuestra hoja de estilos. Para ello utilizaremos la propiedad «content». Vamos con un ejemplo, en el que añadiremos la palabra «Error» antes de un mensaje de error (vamos primero con lo más simple)

.error:before{
  content:"Error: ";
}

Furrula hasta en IE8 (7 no, no pidáis milagros), así que podéis ir trasteando con esto. Hay más posibilidades, claro, porque si sólo pudiéramos meter un textillo la cosa quedaría sosa. Lo primero, podemos dar estilos al contenido generado por estos elementos, como con cualquier otro elemento textual de la web:

.error:before{
  content:"Error: ";
  color:#FF0000;
  font-weight: bold;
}

O podemos incluir una imagen en lugar de un texto:

.error:before{
  content:url("carpetaimagen/imagenejemplo.png");
}

O crear un contenedor:

.error:before{
  content:"";
  display:block;
  background-color:#666;
  width:32px;
  height:32px;
  border:2px solid #ff0000;
}

Eso sí, hay una cosa que debemos tener en cuenta: a la hora de accesibilidad y del uso de lectores de pantalla, por ejemplo, estos textos/imágenes están generados por CSS, no son parte del DOM, no forman parte del contenido en si de la web, por lo que no serán interpretados por estos. Es decir, mejor no crear contenido relevante con esto, tanto por la accesibilidad como por el hecho de que los buscadores no lo indizarán.

La propiedad css background-size y como hacerla funcionar en IE8

Si usas una imagen de fondo en alguna ocasión te habrás visto en la necesidad de usar una que se adapte al tamaño del elemento contenedor. La propiedad CSS3 background-size permite definir el tamaño de esta imagen, ya sea en píxeles o con un porcentaje relativo al tamaño del contenedor. Se definen dos parámetros para el tamaño: el primero es el alto y el segundo el ancho.

/*Este daría un alto de 250px y un ancho de 50*/
background-size:250px 50px; 
/*Este cubriría todo el contenedor*/
background-size:100% 100%;

Como os podéis imaginar, si andáis modificando tamaños la imagen se deformará al romperse la proporción de las medidas.

Existen además de estas medidas dos propiedades que podéis aplicar: cover y contain.

  • Contain: Esta propiedad escala la imagen de forma que mantenga las proporciones y ocupa o el alto o el ancho (dependiendo de la proporción)
  • Cover:Esta propiedad escala la imagen al mínimo tamaño, manteniendo también las proporciones, para que ocupe todo el contenedor. Es posible que esto provoque que parte de la imagen no se vea.
background-size:contain; 
background-size:cover;

Y ahora vamos con el problema (con el que me vi esta tarde): hemos acabado de maquetar, probamos en todos los navegadores y funciona. Entonces en Explorer empezamos con los modos de compatibilidad, y sin problemas en Explorer 10 y 9 pero, al llegar al 8, todo a tomar por culo… tras maldecir a Bill Gates, a Windows, al Explorer y compartir mis cuitas con los compañeros de curro toca buscar una solución… y aparece en StackOverflow, como no.

Con lo que basándome en eso, dejo el css como está, con su background-size que está furrulando en todos los navegadores (menos en Explorer 8 y previos) y en el marcado html modifico el div con el siguiente código, para que así la imagen ocupe todo el contenido:

<div style='filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/logo.gif',sizingMethod='scale');-ms-filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/logo.gif',sizingMethod='scale')";'></div>

En fin, hasta que no queden eliminados todos los IE8 habrá que recurrir a este truquito para hacer funcionar esto. Conste que no soy partidario de usar imágenes de fondo, la verdad.

Pie de página siempre al final de la web

Seguro que alguna vez os ha pasado que os trabajáis una maquetación que se ve de puta madre en vuestra pantalla de 15 pulgadas, pero al verla en una 22… ale, el pie al medio de la página. No hay contenido suficiente para llenar toda esa pantalla. Una opción es usar un posicionamiento absoluto, pero claro, si es una web con varias páginas igual en otra sí tienes suficiente contenido y entonces te queda un pie fijo en la parte de abajo del monitor aunque tengas que scrollear para ver toda la info.

Pero hay una solución, básicametne consiste en envolver todo el contenido superior al footer en un div contenedor, darle un alto mínimo del 100% de la pantalla, meterle debajo un margen negativo y allí insertar el pie. Ok, dicho así suena muy árido. Vamos con un ejemplo progresivo. Imaginemos que el que sigue es nuestro código:

<div id="header">Aquí la cabecera</div>
    <div id="nav">
       <ul>
          <li><a href="#">Inicio</a></li>
          <li><a href="#">Primera</a></li>
          <li><a href="#">Segunda</a></li>
       </ul>
     </div>
<div id="content">Contenido interesante y original que te hará ganar posicionamiento en google.</div>

<div id="footer">Y aquí ese pie que no se nos queda abajo.</div>

Bueno, pues lo primero es el marcado (luego ya nos ponemos con el CSS). La idea es, como he dicho, encerrar todo el contenido en un div que será un contenedor general, y por si acaso al final de este metemos un div vacío con la misión de evitar problemas si hay elementos flotados encima.

<div id="container"> <!--El container-->
  <div id="header">Aquí la cabecera</div>
    <div id="nav">
       <ul>
          <li><a href="#">Inicio</a></li>
          <li><a href="#">Primera</a></li>
          <li><a href="#">Segunda</a></li>
       </ul>
     </div>
  <div id="content">Contenido interesante y original que te hará ganar posicionamiento en google.</div>
  <div class="clear"></div><!--El citado div para evitar problemas con "flotaciones"-->
</div><!--cerramos el container-->
<div id="footer">Y aquí ese pie que no se nos queda abajo.</div>

Bueno, eso está listo. Ahora toca ceeseesear (CSS) todo. Como ya he dicho, la idea es dar a todo el contenedor un tamaño mínimo del 100% de la altura, meterle un margen negativo por abajo y allí insertar el pie. Vamos a meter un pie de 50px de alto en el ejemplo.

/*Lo primero, todo el cuerpo que ocupe el 100%*/
html, body {    
   height: 100%; 
}

/*Lo segundo, el container, con algura mínima del 100% y un margen inferior negativo igual al alto que queramos darle al pie*/
#container {
   min-height: 100%;
   margin-bottom: -50px;
   position: relative;
}

/*Lo tercero, el pie con la altura deseada (igual al margen negativo de antes)*/
#footer {
   height: 50px;
   position: relative;
}

/*Y terminamos con el clear, que ha de ser tan alto como el pie y "limpiar" todos los floats*/
.clear{
   height: 50px;
   clear: both;
}

Y con esto ya está, en todos los navegadores superiores a IE6 (y como IE6 está descontinuado por Microsoft ni me voy a molestar en buscar solución, aunque creo que basta con cambiar el min-height del container por height).

Artículo dedicado con cariño a Gaius Baltar, que se lo había prometido en el feisbuck… jojojo

Display inline-block en Explorer 6, Explorer 7 y Explorer 8

Si maquetáis web es posible que utilizáseis alguna vez la propiedad display:inline-block en vuestro CSS a la hora de posicionar divs o elementos de lista, ya que funciona de una forma muy cómoda. ¿Problemas de usarla? Que en en las versiones anteriores a Explorer 8 no va (este inclusive).

Actualmente, por suerte, casi nadie tiene Explorer 7 (y menos Explorer 6) y los que queden se irán al guano cuando Microsoft deje de dar soporte a XP en 2014, pero todavía hay varios Windows Vista con Explorer 8 rulando por ahí, además también hay administraciones, clínicas o empresas con equipos arcaicos y sin actualizar. ¿Solución? Algunos te dirán «no la uses»… pues no, hay un simple hack, que podéis ver en el ejemplo:

elementoAPosicionar {
    display: inline-block;
    *display: inline;
    zoom: 1;
}

Con esto usamos un Safe CSS Hack para que IE7 interprete bien nuestro CSS. Otra posibilidad es que no funcione por culpa de la declaración del DOCTYPE (Explorer es muy puñetero). Si pasáis de Explorer 7 y sólo os preocupa el 8, basta añadir esto al principio del archivo HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Y creo que si lo declaráis como HTML5 con esta cabecera también funciona:

<!DOCTYPE html>

Por suerte a partir de Explorer 9 muchas de estas cosas se han ido estandarizando, y de momento en Explorer10 lo único que me ha fallado ha sido una animación CSS3, lo cual respecto a hace años es un enorme avance para los chicos de Microsoft. Igual en IE12 ya no hace falta hacer un CSS específico para Explorer.

Títulos de apertura con CSS3

En fin, para empezar este artículo sobre animaciones sobre títulos en CSS3 primero echad un ojo a esta página de ejemplo.Vamos a trabajar para hacer algo similar (bueno, de hecho para hacer ese ejemplo).

Ojo, yo no me he currado el css en este caso, me la encontré mientras me documentaba para otra cosa a través de este artículo, y creo que merece que lo traduzca/explique en castellano.

Años atrás un efecto como este sólo sería posible con Flash, pero ahora podemos hacerlo con la tecnología nativa de los navegadores (bueno, como siempre con la excepción de nuestro querido Internet Explorer, al menos hasta la versión 10). Cierto que en este caso también hay ayuda de un poco de Javascript, no es CSS puro, pero se trata de una simple librería que permitirá trabajar con las letras por separado sin tener que crear nosotros a mano un span para cada una. La biblioteca de JS a utilizar será Lettering.js.

Por tanto vamos primero con el marcado. Crearemos un div para envolverlo todo y meteremos dentro de él todas las frases a usar como títulos de segundo nivel (h2):

</pre>
<div class="hiddenSpellError">class="os-phrases"></div>
<pre></pre>
<h2>Sometimes it's better</h2>
<pre>
    <h2>to hide</h2></pre>
<h2>in order to</h2>
<pre>
    <h2>survive evil</h2>
    <h2>Thanatos</h2>
    <h2>This fall</h2>
    <h2>Prepare</h2>
    <h2>Refresh to replay</h2>
</div>

Ok, ya tenemos el marcado. Como dije antes, toca meter una línea de javascript (en este caso, con jQuery además)

$("#os-phrases > h2").lettering('words').children("span").lettering().children("span").lettering();

Esto lo que hará será, primero, separar cada título en palabras y cada palabra en letras, y además cada letra está metida en dos span distintos con la misma clase. En la página original podéis ver un ejemplo de cómo sería hacer eso codeándolo a mano.

Muy bien, ya tenemos la parte de marcado lista, a base tanto de código manual como de javascript para facilitar las tareas. Toca ponerse manos a la obra con el CSS.

Lo primero será lograr que nuestros títulos ocupen el 100% de la página, posicionado de forma absoluta, en mayúsculas y bien tocho:

.os-phrases h2 {
    font-family: 'Dosis', 'Lato', sans-serif;
    font-size: 70px;
    font-weight: 200;
    height: 100%;
    width: 100%;
    overflow: hidden;
    text-transform: uppercase;
    padding: 0;
    margin: 0;
    position: absolute;
    top: 0;
    left: 0;
    letter-spacing: 14px;
    text-align: center;
}

Right now! Este paso ya está listo, el título es bien tochaco. Eso sí, podría pasar que no se ajustase bien a todos los tamaños de pantalla, así que vamos a usar flexbox para solucionarlo.

.os-phrases h2,
.os-phrases h2 > span {
    height: 100%;
    /* Centrando con flexbox */
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

El siguiente paso es meter espaciado entre palabras:

.os-phrases h2 > span {
    margin: 0 15px;
}

Y ahora vamos a ver el por qué de los dos span para cada letra. Al primero de ellos le vamos a aplicar perspectiva:

.os-phrases h2 > span > span {
    display: inline-block;
    perspective: 1000px;
    transform-origin: 50% 50%;
}

Las letras en si serán transparentes y les meteremos una animación, que durará 5.2 segundos.

.os-phrases h2 > span > span > span {
    display: inline-block;
    color: hsla(0,0%,0%,0);
    transform-style: preserve-3d;
    transform: translate3d(0,0,0);
    animation: OpeningSequence 5.2s linear forwards;
}

Con esto ya ves la lógica del doble span.

Una vez tenemos la orientación de las letras toca definir los delays de las frases. La quinta frase, la que es el título de la «película imaginaria» tendrá un delay especial, aparecerá más lentamente. En cambio las secuencias 6 y 7 irán más rápido.

.os-phrases h2:nth-child(2) > span > span > span {
    animation-delay: 5s;
}

.os-phrases h2:nth-child(3) > span > span > span {
    animation-delay: 10s;
}

.os-phrases h2:nth-child(4) > span > span > span {
    animation-delay: 15s;
}

.os-phrases h2:nth-child(5) > span > span > span {
    font-size: 150px;
    animation-delay: 21s;
    animation-duration: 8s;
}

.os-phrases h2:nth-child(6) > span > span > span {
    animation-delay: 30s;
}

.os-phrases h2:nth-child(7) > span > span > span {
    animation-delay: 34s;
}

Antes de meternos con la última frase, que tendrá un tratamiento más especial, toca definir cómo se comportarán las letras durante la animación (es decir, cómo va evolucionando la separación, la opacidad, etc durante la animación):

@keyframes OpeningSequence {
    0% {
        text-shadow: 0 0 50px #fff;
        letter-spacing: 80px;
        opacity: 0.2;
        transform: rotateY(-90deg);
    }
    50% {
        text-shadow: 0 0 1px #fff;
        letter-spacing: 14px;
        opacity: 0.8;
        transform: rotateY(0deg);
    }
    85% {
        text-shadow: 0 0 1px #fff;
        opacity: 0.8;
        transform: rotateY(0deg) translateZ(100px);
    }
    100% {
        text-shadow: 0 0 10px #fff;
        opacity: 0;
        transform: translateZ(130px);
        pointer-events: none;
    }
}

Ok, con esto ya tenemos todo lo relativo a todas las frases… menos la última, que ya dijimos que tendría un tratamiento especial, ya que la animación será distinta al resto, usando en este caso un fundido:

.os-phrases h2:nth-child(8) > span > span > span {
    font-size: 30px;
    animation: FadeIn 4s linear 40s forwards;
}

@keyframes FadeIn {
    0% {
        opacity: 0;
        text-shadow: 0 0 50px #fff;
    }
    100% {
        opacity: 0.8;
        text-shadow: 0 0 1px #fff;
    }
}

Y ahora pensarás «¿No había algunas palabras destacadas?». Y tienes razón, algunas estaban en negrita. Pero tranqui, eso lo arreglamos con esta última línea, donde aplicamos la negrita a ciertas palabras concretas:

.os-phrases h2:first-child .word3,
.os-phrases h2:nth-child(2) .word2,
.os-phrases h2:nth-child(4) .word2 {
    font-weight: 600;
}

En fin, ya ves que es un pelín tocho el código pero que tampoco come a nadie, y se logra un resultado muy espectacular. Si no os apetece copiar, el código original está en este enlace.

A la hora de terminar este artículo, la web original estaba en remodelación. Pero echadle un ojo por si acaso porque cuando vuelva a estar activa tiene muchos trucos de diseño web muy interesantes, como todos los que ha colgado la creadora de este efecto Mary Lou.

Interlineado en CSS

Una entrada simple y básica de CSS ¿Quieres modificar el interlineado de un texto en tu web? Es muy simple.

El interlineado es la separación existente entre las líneas de un mismo texto. Por defecto en html se aplica un interlineado sencillo, pero podéis usar css para cambiarlo. La propiedad que debéis usar es line-height, tal cual así:


line-height: 1.3em;

Como siempre podéis definir las medidas del ancho de línea en diversas unidades: píxeles, centímetros, em, un porcentaje. Si queréis que mantenga la proporción respecto al texto lo más recomendable es usar em, si queréis un tamaño fijo px y para diseños fluídos porcentaje.

Colorzilla: Complemento productivo para desarrolladores

¿Te ha pasado alguna vez de ver en una web y decir «Ese es el color que quiero para mi cabecera»? Bueno, Colorzilla te permite integrar en tu navegador (Chrome o Firefox) una serie de herramientas relacionadas con el tema de la elección/búsqueda de colores que puede facilitar tu trabajo como desarrollador.

En principio lo que yo buscaba era un simple Eyedropper para mi navegador, es decir, una aplicación que me permitiera conocer el código RGB de un color que esté saliendo en mi pantalla. Esta es la función principal de Colorzilla, pero no la única ni la más potente. También nos dota de un selector de color (Colorpicker) y un navegador de paletas que agilizan bastante el trabajo (combínalo, por ejemplo, con Firebug y piensa en la velocidad de poder probar todo eso en el navegador) y que además nos deja salvar colores y paletas como «favoritos».

Pero las dos herramientas más interesantes, y más potentes, creo que son el generador de degradados, que te permite modificar varias plantillas y te da el código CSS pensado para mantener la compatibilidad con navegadores obsoletos, y el Web Page DOM Color Analizer. Este último se tira un ratito analizando una página y finalmente te da todos los colores que se han usado en la misma, informándote sobre qué elementos usan cada uno. Esto te ayudará a hacerte una idea al respecto del diseño del sitio.

Resumiendo, un complemento ligero que puede ser muy útil y productivo a la hora de trabajar desarrollando un front-end.

Zoom sobre texto con CSS3 usando transiciones

Otra nueva entrada sobre las virtudes de CSS3, en este caso vamos a hacer una pequeña introducción a las transiciones creando un código que nos permita que la letra de un párrafo aumente de tamaño cuando el ratón esté sobre ella.

Para ello por un lado tendremos que definir la transición sobre el elemento a modificar y luego la modificación cuando se produzca el evento.

Lo primero sería así:

.aumenta {
    font-size: 1.1em;
    width: 300px;
 
    -moz-transition: font-size 500ms linear 0s; 
    -webkit-transition: font-size 500ms linear 0s;
    -o-transition: font-size 500ms linear 0s;
    transition: font-size 500ms linear 0s;
}

Explicación: tras definir el tamaño del texto para la clase aumenta (1.1 em) definimos la transición. Hay varios métodos para la transición, así que he usado la propiedad shorthand de transition. El primer parámetro (font-size) es para especificar a qué propiedad se aplicará la transición, el segundo el tiempo que tardará, el tercero que se hará siempre a la misma velocidad (linear) y el cuarto que se haga sin delay.

Y ahora que tenemos la transición definida para todos los navegadores (ojo!!! Explorer 9 no soporta todavía transiciones, dice Bill Gates que igual para la 10) toca definir cómo se transformará el texto cuando esté sobrevolado por el ratón:

.aumenta:hover{
    font-size:1.6em;
}

Definimos que en el evento hover la fuente pase a ser más grande. Con esto ya tenemos nuestra transición lista.

Crear un chat con PHP y jQuery

En este caso no se trata de un artículo original, sino de una medio traducción medio interpretación de este original en inglés. Podéis descargaros todo el código desde el enlace.

Se trata de un chat web simple, programado en php y basado en Ajax, haciendo uso de jQuery, con función de login y logout y soporte para varios usuarios.

El tutorial comienza creando un archivo index.php tal cual este:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
<title>Chat - Customer Module</title>  
<link type="text/css" rel="stylesheet" href="style.css" />  
</head>  
<div id="wrapper">  
    <div id="menu">  
        <p class="welcome">Welcome, <b></b></p>  
        <p class="logout"><a id="exit" href="#">Exit Chat</a></p>  
        <div style="clear:both"></div>  
    </div>  
    <div id="chatbox"></div>  
    <form name="message" action="">  
        <input name="usermsg" type="text" id="usermsg" size="63" />  
        <input name="submitmsg" type="submit"  id="submitmsg" value="Send" />  
    </form>  
</div>  
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.0.js"></script>  
<script type="text/javascript">  
// jQuery Document  
$(document).ready(function(){  
});  
</script>  
</body>  
</html>

Como podéis ver se trata de un marcado HTML normal. La referencia a jQuery del código original está anticuada, en este ejemplo ya veréis una apuntando una dirección actualizada. En cuanto a la estructura hay tres grandes divs: el #wrapper, que contiene los otros dos y el formulario de envío de mensaje; el #menu, que sólo es un mensaje de bienvenida y un botón de logout y, finalmente, el #chatbox, que es donde se incluirán los mensajes.

El css sería tal que así:

    /* CSS Document */  
    body {  
        font:12px arial;  
        color: #222;  
        text-align:center;  
        padding:35px; }  
    form, p, span {  
        margin:0;  
        padding:0; }  
    input { font:12px arial; }  
    a {  
        color:#0000FF;  
        text-decoration:none; }  
        a:hover { text-decoration:underline; }  
    #wrapper, #loginform {  
        margin:0 auto;  
        padding-bottom:25px;  
        background:#EBF4FB;  
        width:504px;  
        border:1px solid #ACD8F0; }  
    #loginform { padding-top:18px; }  
        #loginform p { margin: 5px; }  
    #chatbox {  
        text-align:left;  
        margin:0 auto;  
        margin-bottom:25px;  
        padding:10px;  
        background:#fff;  
        height:270px;  
        width:430px;  
        border:1px solid #ACD8F0;  
        overflow:auto; }  
    #usermsg {  
        width:395px;  
        border:1px solid #ACD8F0; }  
    #submit { width: 60px; }  
    .error { color: #ff0000; }  
    #menu { padding:12.5px 25px 12.5px 25px; }  
    .welcome { float:left; }  
    .logout { float:rightright; }  
    .msgln { margin:0 0 2px 0; }  

Poca cosa que comentar, pero entre esto y el marcado ya tenemos la apariencia definida del chat.

Ahora toca el formulario de login en PHP:

    <?  
    session_start();  
    function loginForm(){  
        echo' 
        <div id="loginform"> 
        <form action="index.php" method="post"> 
            <p>Please enter your name to continue:</p> 
            <label for="name">Name:</label> 
            <input type="text" name="name" id="name" /> 
            <input type="submit" name="enter" id="enter" value="Enter" /> 
        </form> 
        </div> 
        ';  
    }  
    if(isset($_POST['enter'])){  
        if($_POST['name'] != ""){  
            $_SESSION['name'] = stripslashes(htmlspecialchars($_POST['name']));  
        }  
        else{  
            echo '<span class="error">Please type in a name</span>';  
        }  
    }  
    ?>     

En este caso se trata de un login simple, no comprueba usuarios registrados en una base de datos. Sobre su funcionamiento hay poco que comentar: nos pide un nombre y lo incluye dentro de una variable de sesión (de ahí la llamada a session_start()). El uso de htmlspecialchars() es para evitar ataques XSS.

Lo siguiente es motrar tanto el nombre de usuario en el Welcome como el formulario si el usuario no está logueado. La idea es dejar el primer archivo, el index.php tal cual este:

    <?php  
    if(!isset($_SESSION['name'])){  
        loginForm();  
    }  
    else{  
    ?>  
    <div id="wrapper">  
        <div id="menu">  
            <p class="welcome">Welcome, <b><?php echo $_SESSION['name']; ?></b></p>  
            <p class="logout"><a id="exit" href="#">Exit Chat</a></p>  
            <div style="clear:both"></div>  
        </div>  
        <div id="chatbox"></div>  
        <form name="message" action="">  
            <input name="usermsg" type="text" id="usermsg" size="63" />  
            <input name="submitmsg" type="submit"  id="submitmsg" value="Send" />  
        </form>  
    </div>  
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>  
    <script type="text/javascript">  
    // jQuery Document  
    $(document).ready(function(){  
    });  
    </script>  
    <?php  
    }  
    ?>  

Bien, ahora vamos con el código de Javascript para la funcionalidad de logout. Dentro del script que ya tenemos creado en nestro código insertamos:

    <script type="text/javascript">  
    // jQuery Document  
    $(document).ready(function(){  
        //If user wants to end session  
        $("#exit").click(function(){  
            var exit = confirm("Are you sure you want to end the session?");  
            if(exit==true){window.location = 'index.php?logout=true';}  
        });  
    });  
    </script>  

Esto no sólo nos permite enviar una llamada por el método GET para desconectar al usuario, sino que también nos sacará una ventana de confirmación antes de hacerlo. Y claro está, tendremos que tocar nuestro código del index.php para comprobar que se ha hecho una petición de logout y destruir la sesión que se había creado en el login:

    if(isset($_GET['logout'])){  
        //Simple exit message  
        $fp = fopen("log.html", 'a');  
        fwrite($fp, "<div class='msgln'><i>User ". $_SESSION['name'] ." has left the chat session.</i><br></div>");  
        fclose($fp);  
        session_destroy();  
        header("Location: index.php"); //Redirect the user  
    }  

Este código, además, escribe en un archivo de logs (más tarde vemos para qué se usará) que el usuario se ha desconectado y redirecciona de nuevo a la página principal.

Lo siguiente es manejar las inserciones de mensajes de los usuarios. Hay que empezar por definir una función de jQuery para enviar los mensajes por el método POST haciendo uso de Ajax. El proceso sería recoger el evento de click del formulario, leer los datos del campo de texto, enviarlos al script de php que los va a tratar y borrar el campo de texto para que quede de nuevo en blanco:

    //If user submits the form  
    $("#submitmsg").click(function(){  
        var clientmsg = $("#usermsg").val();  
        $.post("post.php", {text: clientmsg});  
        $("#usermsg").attr("value", "");  
        return false;  
    });  

Y claro, esto implica crear el archivo post.php para manejar los datos en el lado del servidor. Un archivo que llevaría este código:

    <?  
    session_start();  
    if(isset($_SESSION['name'])){  
        $text = $_POST['text'];  
        $fp = fopen("log.html", 'a');  
        fwrite($fp, "<div class='msgln'>(".date("g:i A").") <b>".$_SESSION['name']."</b>: ".stripslashes(htmlspecialchars($text))."<br></div>");  
        fclose($fp);  
    }  
    ?>  

De nuevo iniciamos sesión, comprobamos que el usuario está logueado, recogemos el texto del mensaje del array $_POST y escribimos el mensaje junto al nombre de usuario en el log del chat.

Finalmente llevamos a la parte de mostrar los mensajes de chat en pantalla. Lo primero es cargar el log del chat dentro del #chatbox si este existe, para ahorrarnos tiempo:

    <div id="chatbox"><?php  
    if(file_exists("log.html") && filesize("log.html") > 0){  
        $handle = fopen("log.html", "r");  
        $contents = fread($handle, filesize("log.html"));  
        fclose($handle);  
        echo $contents;  
    }  
    ?></div>  

Lo siguiente es la carga por Ajax de los datos contenidos en el archivo de log. La cosa se arreglaría con el método de jQuery para Ajax:

    //Load the file containing the chat log  
        function loadLog(){  
            $.ajax({  
                url: "log.html",  
                cache: false,  
                success: function(html){  
                    $("#chatbox").html(html); //Insert chat log into the #chatbox div  
                },  
            });  
        }  

El parámetro url nos indica a qué archivo intentamos acceder por Ajax, cache es para definir si queremos cachear el archivo o no (en este caso, por lógica, no, porque queremos recargarlo en cada llamada) y finalmente la función que se ejecutará en caso de éxito (en este caso insertar el log en el div #chatbowx).

Para añadir autoscrolling, modificas el código anterior añadiendo lo siguiente:

    //Load the file containing the chat log  
    function loadLog(){  
        var oldscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height before the request  
        $.ajax({  
            url: "log.html",  
            cache: false,  
            success: function(html){  
                $("#chatbox").html(html); //Insert chat log into the #chatbox div  
                //Auto-scroll  
                var newscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height after the request  
                if(newscrollHeight > oldscrollHeight){  
                    $("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll to bottom of div  
                }  
            },  
        });  
    }  

Básicamente consiste en ir modificando el tamaño para ocultar la parte de arriba y ampliar la de abajo. Simple truquillo. Ahora nos falta que el chat se auto recargue, cosa que haremos desde javascript:

setInterval (loadLog, 2500);

Esto lanza la función loadLog cada dos segundos y medio, logrando recargar los datos.

En el artículo orginal además encontraréis al final una serie de artículos con consejos varios para mejorar el código (en inglés) y todo el código completo para descargar.

Diferencia entre display:none y visibility:hidden en CSS

A la hora de ocultar elementos html desde el css tenemos dos posibilidades: las propiedades display  y visibility. Ambas nos permiten definirlas para que un elemento no se muestre en nuestra página. En caso de display definiéndola como display:none y en caso de visibility como visibility:hidden. Muchos son los inconscientes que los usan de manera indistinta, con fatídicas consecuencias para sus maquetaciones porque ambas propiedades tienen diferencias. Veamos cuales:

  • La propiedad visibility:hidden oculta un elemento de la vista del usuario, pero respetando el espacio que ocupaba. Imagina que tienes tres cuadrados y ocultas el del medio con esta propiedad, ¿ok? Lo que ocurriría es que el cuadrado desaparecería, dejando ver lo que haya de fondo, y los cuadrados 1 y 3 seguirían en la misma posición. Con visibility:hidden todas las cajas css siguen en su sitio.
  • La propiedad display:none no sólo oculta, sino que quita el elemento del flujo lógico de la maquetación. Imagina el mismo caso de los cuadrados, en este supuesto en cambio el tercer cuadrado se desplazaría hacia la izquieda, ocupando el espacio que antes ocupaba el 2. Es decir, cuando usas display:none todas las cajas se recolocan como si la caja oculta no existiera.

Por tanto, a la hora de usar una propiedad u otra ten en cuenta estos comportamientos por el bien de tu maquetación.