Entradas etiquetadas con Maquetación

jquery-logo

jQuery.height() calcula distintos tamaños entre navegadores [solución]

Este es un tip rápido pero útil.

Escenario:
Tenes un div con el id “elDiv” con el siguiente CSS:

#elDiv {
	border: 1px solid #336699;
	float: right;
	padding: 20px;
	width: 500px;
}

Y en Firefox/Chrome/Safari/Opera al hacer $(“#elDiv”).height(); te entrega 400px por decir algo (el tamaño depende de lo que tenga dentro).
Pero curiosamente en Internet explorer te da un tamaño raro… de menos, unos 358px en nuestro ejemplo.

¿Qué pasa?
Pasa que no le especificaste un modo de renderizado al HTML por medio del DOCTYPE, y por culpa de ello Internet explorer va a renderizar el contenido en modo “Quirks Modehttp://es.wikipedia.org/wiki/Quirks_Mode.

Si no queres leer el articulo de Wikipedia te comento que lo único que tenes que hacer es poner lo siguiente por encima del tag <html>:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">

PD: el valor de 358px en mi ejemplo viene de que en modo quirks, IE toma el tamaño del tamaño real menos el padding y el borde: 400 – 40 – 2 = 358.

internet-explorer-logo

Algunos CSS no cargan en Internet Explorer

Me rompí un poco la cabeza con este asunto: Hago unas modificaciones que se ven mas que bien en todos los navegadores menos en IE como siempre, y por ello tengo un ie.css puntual para hacer todas las cosas raras que se suelen hacer con CSS para que IE trague.

El problema me lo di con que Internet Explorer 7 (no recuerdo si el 8 también) no reflejaba los cambios de mi CSS destinado a el…. :S

Pero ya se cual es el problema y como no, la solución ;)

El problema es que Internet Explorer por algún misterioso motivo solo carga hasta 31 CSS (los <style> inline también cuentan o_O), y mi CSS especial ya estaba por el puesto 32…

La primera solución que se me ocurrió es activar la compresión de CSS para que se haga uno o dos CSS, pero lo que tiene de malo eso es que si estas maquetando te vas a querer pegar un tiro a la 10º vez que tengas que borrar el cache para ver si el texto que estas maquetando se termina de ver bien en la bass.. Internet Explorer.
Así que fui a darme una vuelta por los módulos de Drupal… Bingo. Hay un modulo que nos salva las papas. Se llama “IE CSS Optimizer”, y lo que hace básicamente es añadir dos opciones más a la compresión de los CSS:

Y lo que hace es algo de lo más simple. Comprime todo el CSS en un archivo pero sin cachearlo.

Con este modulito ya no vas a tener que preocuparte del rarísimo límite de 31 archivos.

Una ultima anotación a todo esto es que andar va a andar bien, pero no vayas a olvidar de poner de nuevo la configuración de la compresión del CSS a “Full optimization” para producción.

druplicon

Aplicar un theme, plantilla o template a formularios en Drupal 6

Supongamos que tenemos un formulario que creamos para que se vea en la URL

http://www.ejemplo.com/themed_form

El formulario definido en el modulo tendría una pinta como la siguiente:

function formulario(){
 $form['nombre'] = array(
 '#title' => t('Nombre'),
 '#type' => 'textfield',
 );

 $form['apellido'] = array(
 '#title' => t('Apellido'),
 '#type' => 'textfield',
 );

 $form['mail'] = array(
 '#title' => t('e-mail'),
 '#type' => 'textfield',
 );

 $form['telefono'] = array(
 '#title' => t('Teléfono'),
 '#type' => 'textfield',
 );

 $form['submit'] = array(
 '#type' => 'submit',
 '#value' => t('Enviar'),
 );
 return $form;
}

Y el hook_menu tendría una pinta como esta:

function theme_form_sample_menu(){
 $items['themed_form'] = array(
 'title' => 'Muestra de themado de un formulario',
 'page callback' => 'render_formulario',
 'access arguments' => array(true),
 'type' => MENU_CALLBACK,
 );
 return $items;
}

Y la función para aplicar sobre la url seria:

function render_formulario(){
	//podemos agregar nuestros extras.
	drupal_add_js(drupal_get_path('module', 'theme_form_sample') .'/js/ejemplo.js');
	drupal_add_css(drupal_get_path('module', 'theme_form_sample') .'/css/ejemplo.css');

	//ya podemos generar el formulario.
	return drupal_get_form("formulario");
}

El formulario se va a dibujar correctamente y lo podemos maquetar con CSS si queremos, pero, y si además de los elementos del formulario tenemos que meterle mas HTML ¿que hacemos?.

¿Modificamos la función que define al formulario metiéndole markups por todos lados?. Pues no.

¿Entonces cual es la forma en la que los formularios en drupal 6 se maquetan?:

Fácil. Agregas una linea mas en la definición del formulario como esta:

$form['#theme'] = "theme_para_formulario";

La podes poner al principio o justo al final antes del return para mayor comodidad.

Ahora bien, esto no es todo (si la vida fuera tan simple…), además nos hace falta definir el hook_theme():

function theme_form_sample_theme() {
 return array(
 'theme_para_formulario' => array(
 'template' => 'formulario',
 'arguments' => array('form' => NULL),
 ),
 );
}

(Noten que en el argumento paso una variable llamada “form”)

Ahora creamos la plantilla “formulario.tpl.php” y agregamos el siguiente código:

echo drupal_render($form);

Guardarlo, limpia la cache y probalo.

Podes ver que el formulario ahí está, se dibuja, pero claro, seguís sin poder manosear sus elementos por separado. Solucionemos eso o mi post va a dejar de tener sentido:

Cambiemos el anterior código de la plantilla (echo drupal_render($form);) por este otro:

<?php echo drupal_render($form["apellido"]); ?>;
<?php echo drupal_render($form["mail"]); ?>;
<?php echo drupal_render($form["telefono"]); ?>;
<?php echo drupal_render($form["nombre"]); ?>;

Como se puede ver, lo que estoy haciendo es renderizar uno a uno los elementos del formulario.

En el ejemplo anterior recordaras que hicimos algo así como “drupal_render($form)”. Bueno lo que pasa allí básicamente es que toma el array que definiste en la función y lo convierte en HTML, Y como nosotros queremos poder renderizar las partes del formulario por separado la teoría dice que si en lugar de mandar el array entero, mandamos un pedasito, debería funcionar, y es justamente lo que ha pasado en el segundo ejemplo.

pero falta algo acá.. el resto del formulario. Sin ir mas lejos falta el botón de envío, los token, el form_id (lo pueden ver el el código fuente de la pagina renderizada).

Eso pasa porque nosotros ya podemos controlar cuales elementos vamos a mandar a renderizar por separado, pero no le hemos dicho que hacer con el resto. Solucionemos esto agregando esta linea al justo debajo de las anteriores:

<?php echo drupal_render($form); ?>

Guardar, probar, Alegrarse.

Ahora solo nos queda aprovechar que estamos parados en una plantilla y agregar el HTML que nos haga falta para poder darle la forma que queramos:

<div>

 <div>
 <!-- Si comentas esta linea vas a ver que se sigue dibujando el formulario entero -->
 <?php echo drupal_render($form["apellido"]); ?>
 <?php echo drupal_render($form["mail"]); ?>
 </div>

 <div>
 <?php echo drupal_render($form["telefono"]); ?>
 <?php echo drupal_render($form["nombre"]); ?>
 </div>

 <div>&nbsp;</div>

 <!-- si comentas esta linea vas a ver como el resto de los elementos del formulario no se dibujan -->
 <?php echo drupal_render($form); ?>

 <div>&nbsp;</div>

</div>

Para rematar el asunto, hice un modulito de ejemplo que podes descargar activar y probar en la url http://tuservidor.de.desarrollo.com/themed_form

Descargar módulo de ejemplo

Bueno espero que les sirva. Bye.

Opciones de esquinas redondeadas para internet explorer 6, 7 y 8

Hace casi un año me vi en la tarea de investigar una vez mas cual era la mejor forma de obtener bordes redondeados para estos navegadores pero esta vez teniendo en cuenta la velocidad de desarrollo.

Las opciones que tenia a mano eran:

La mas tradicional, anidar divs hasta el cuatro niveles para poder colocar imágenes en cada una de las esquinas:

<div class="redondeo">
    <div>
        <div>
            <div>
                <h2>Lorem ipsum dolor</h2>
                <div class="contenido">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit...
                </div>
            </div>
        </div>
    </div>
</div>
* {
    font-family: Verdana;
}

.redondeo {
    background: url("images/esq_sup_2-1.png") no-repeat scroll 100% 100% transparent;
    width: 300px;
}

.redondeo div {
    background: url("images/esq_sup_1-1.png") no-repeat scroll 0 100% transparent;
}

.redondeo div div {
    background: url("images/esq_sup_2.png") no-repeat scroll 100% 0 transparent;
}

.redondeo div div div {
    background: url("images/esq_sup_1.png") no-repeat scroll 0 0 transparent;
}

.contenido {
    background: none repeat scroll 0 0 transparent !important;
    padding: 0 15px 15px;
    text-align: center;
}

h2 {
    color: #fff;
    text-align: center;
}

Ver ejemplo | Descargar

Este método tiene sus pro y sus contras.
Lo que tiene de bueno es que esta técnica es compatible con todos los internet explorer partiendo de la versión 5 y que la velocidad de renderizado es instantánea.

Lo malo es que es poco mantenible. Lo digo por lo siguiente: pensemos por un momento que tenemos que cambiar el color de la cabecera de la caja de ejemplo. El primer problema es que al ser una imagen que tiene los bordes creados con algún editor de imágenes como Photoshop, Gimp o Paint.NET, para cambiar el color deberíamos recurrir a estas herramientas. Si quisiéramos ponerle un borde de color lo mismo., y ni hablar si queremos remaquetar el site entero.
Y lo anterior es por decir alguno de los casos mas normales, pero hay mas, y quien haya usado esta técnica sabe de lo que hablo.

La segunda opción DD_roundies:

Es la que estuve usando intensamente hasta hace poco. Se trata de una librería JavaScript llamada DD_roundies.
Esta librería redondea cualquier elemento HTML de tipo bloque usando VML para conseguirlo.
Es realmente notable el resultado que se consigue con esta librería. De hecho por un buen tiempo la consideré la solución mas acertada ya que es realmente fácil de usar:

<!-- Agregamos el JS--> <script src="DD_roundies.js"></script> 
//Agregamos el JS
/*
Ahora solo necesitamos decirle a ddroundies sobre que
class o id debe redondear y de cuanto es el radio de
redondeo que debe aplicar */

/**
 * Un redondeo de todos los bordes a 10 pixeles para todos
 * los elementos HTML que lleven definida esta clase
 * */
DD_roundies.addRule('.redondeado-10px', '30px');

/*
 Tambien se puede especificar un redondeo para cada
 una de las esquinas

 5px para la esquina superior izquierda
 10px para la esquina superior derecha
 15px para la esquina inferior derecha
 20px para la esquina inferior izquierda
 */
DD_roundies.addRule('.redondeado-popurri', '5px 10px 15px 30px');
/*
Es opcional definir los css, pero
aca los defino para darles un color
*/

.redondeado-10px {
    background-color: #336699;
}

.redondeado-popurri {
    background-color: #ff0000;
}
<div class="redondeado-10px">
    <br/>
    <br/>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit...
    <br/>
    <br/>
</div>

<br/>

<div class="redondeado-popurri">
    <br/>
    <br/>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit...
    <br/>
    <br/>
</div>

Ver ejemplo | Descargar

Como ven el uso es simple, PEEEERO la gran pega que tiene esta técnica es el hambre voraz de procesador para renderizar las esquinas, brutal, y en un principio para hacer cosas chicas como una o dos cajas redondeadas va de maravilla, pero haganlo con 20 o 30… Mejor NO LO HAGAN, ya les puedo adelantar que la pagina va a quedar congelada varios segundos hasta que termine de dibujar todas las esquinas.

La tercera, curved-corner:

Basada también en VML, es “curved-corner” y Alexis de Eliseos.net ha dedicado un post hace unas semanas.

Esta implementacion fue de las primeras alternativas que conoci hace un tiempo ya, y la usé y deje de usar con la misma rapidez porque tiene dos flaquezas inaceptables y que al dia de hoy no se han solucionado:
La mas importante es que despues de redondear una X cantidad de div o lo que sea, va a fallar y dejar de redondear el resto.
La segunda es que esta solucion a diferencia de la segunda propuesta, solo permite aplicar un redondeo completo al div, dejando fuera la porsibilidad de hacer un redondeo solo a una esquina.

Las otras soluciones:

¿Hay mas? si claro, un millón de soluciones. Las que mas han prosperado son sobre todo las basadas en frameworks js. Un ejemplo es

http://www.malsup.com/jquery/corner/

Pero ni vale la pena ponerse a hablar este tipo de soluciones porque no alcanzan a crear unos bordes tan perfectos como los que logran las anteriores soluciones ya citadas.

Conclusion:

De estas tres tecnicas la mas reocmendable de todas es la de DD_roundies, que mas alla de tener inconvenientes como las otras dos, es la que mas compensa la relacion velocidad de desarrollo – calidad. Lo unico en lo que hay que tener un muy especial cuidado es en no llenar la pagina de bordes redondeados por medio de este metodo porque insisto, van a tener un increible problema de performance.
De hecho, para cerrar este post puedo proponer una solucion hibrida entre la solucion de redondeo por medio de imagenes y la de DD_roundies, usando la primera para cualquier lista de elementos HTML que se repitan contantemente y sean iguales claro, dejando la opcion de DD_roundies para situaciones mas complicadas de solucionar con lo que a diseño respecta.

Firefox

Los anchor en Firefox no van a la posición deseada

Cositas raras como estas me las encuentro todos los días, pero no esta de mas dejar la solución para que no tengan que meterse en foros a buscarla.

Cuando declaras un anchor, si este esta dentro elementos que flotan (a la izquierda o a la derecha), lo mas seguro es que en lugar de parar en el anchor, lo haga por encima de el.

¿La solución?. Flotar el anchor con una class.

Ir arriba