Introducción
Actualización agosto 2019
¿Quieres imprimir con JavaScript sin usar el diálogo de impresión, con la posibilidad de cortar el papel y abrir el cajón de dinero? mira este post.
Recientemente escribí un tutorial sobre cómo imprimir un ticket en una impresora térmica usando PHP. Veamos entonces cómo podemos imprimir ticket en impresora térmica usando JavaScript.
Las complicaciones que tenemos al imprimir con PHP son:
- Confusión de cómo usar la librería
- Forzar a que el lenguaje del servidor sea PHP
Así que ahora decidí hacer una entrada para saber cómo imprimir un ticket en una impresora térmica sin usar PHP, sólo Javascript. El resultado será el siguiente:
Cuando terminemos, la interfaz se verá como aparece abajo. Puedes probarlo directamente haciendo click en Imprimir dentro de este enlace.
Lo único laborioso de esto es diseñar el ticket y adjuntar los productos.
Nota: lo he probado solamente con Chrome. Pero, independientemente del lugar, debemos quitar todos los márgenes y modificar un poco la escala para que el contenido ocupe el mayor espacio posible. Por ejemplo, así se ve sin ningún margen:
Imprimir ticket en impresora térmica usando Javascript
Diseñando el ticket
Vamos a comenzar definiendo un contenedor:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<div class="ticket">
</div>
</body>
</html>
Agregando una tabla
Vamos a tabular todo con una tabla, para que quede alineado:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<div class="ticket">
<table>
<thead>
<tr>
<th>CANT</th>
<th>PRODUCTO</th>
<th>$$</th>
</tr>
</thead>
<tbody>
<tr>
<td>1.00</td>
<td>CHEETOS VERDES 80 G</td>
<td>$8.50</td>
</tr>
<tr>
<td>2.00</td>
<td>KINDER DELICE</td>
<td>$10.00</td>
</tr>
<tr>
<td>1.00</td>
<td>COCA COLA 600 ML</td>
<td>$10.00</td>
</tr>
<tr>
<td></td>
<td>TOTAL</td>
<td>$28.50</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Estilos
Ahora falta definir nuestros estilos:
* {
font-size: 12px;
font-family: 'Times New Roman';
}
td,
th,
tr,
table {
border-top: 1px solid black;
border-collapse: collapse;
}
td.producto,
th.producto {
width: 75px;
max-width: 75px;
}
td.cantidad,
th.cantidad {
width: 40px;
max-width: 40px;
word-break: break-all;
}
td.precio,
th.precio {
width: 40px;
max-width: 40px;
word-break: break-all;
}
.centrado {
text-align: center;
align-content: center;
}
.ticket {
width: 155px;
max-width: 155px;
}
img {
max-width: inherit;
width: inherit;
}
Hay que notar que también definimos algunas clases para centrar texto y algunos estilos para una imagen.
Esto es porque le pondremos un logo más adelante. Por el momento nuestro ticket se ve así.
Logo y pie
Finalmente vamos a agregar un “Gracias por su compra” o algo que nosotros queramos, así como un logo.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<div class="ticket">
<img
src="https://yt3.ggpht.com/-3BKTe8YFlbA/AAAAAAAAAAI/AAAAAAAAAAA/ad0jqQ4IkGE/s900-c-k-no-mo-rj-c0xffffff/photo.jpg"
alt="Logotipo">
<p class="centrado">TICKET DE VENTA<br>New New York<br>17/10/2017
02:22 a.m.</p>
<table>
<thead>
<tr>
<th>CANT</th>
<th>PRODUCTO</th>
<th>$$</th>
</tr>
</thead>
<tbody>
<tr>
<td>1.00</td>
<td>CHEETOS VERDES 80 G</td>
<td>$8.50</td>
</tr>
<tr>
<td>2.00</td>
<td>KINDER DELICE</td>
<td>$10.00</td>
</tr>
<tr>
<td>1.00</td>
<td>COCA COLA 600 ML</td>
<td>$10.00</td>
</tr>
<tr>
<td></td>
<td>TOTAL</td>
<td>$28.50</td>
</tr>
</tbody>
</table>
<p class="centrado">¡GRACIAS POR SU COMPRA!<br>parzibyte.me</p>
</div>
</body>
</html>
Olvidé mencionar que tenemos que asignar las clases a las columnas y filas de las tablas, de la siguiente manera:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css"> <script src="script.js"></script>
</head>
<body>
<div class="ticket">
<img
src="https://yt3.ggpht.com/-3BKTe8YFlbA/AAAAAAAAAAI/AAAAAAAAAAA/ad0jqQ4IkGE/s900-c-k-no-mo-rj-c0xffffff/photo.jpg"
alt="Logotipo">
<p class="centrado">Parzibyte's blog
<br>New New York
<br>23/08/2017 08:22 a.m.</p>
<table>
<thead>
<tr>
<th class="cantidad">CANT</th>
<th class="producto">PRODUCTO</th>
<th class="precio">$$</th>
</tr>
</thead>
<tbody>
<tr>
<td class="cantidad">1.00</td>
<td class="producto">CHEETOS VERDES 80 G</td>
<td class="precio">$8.50</td>
</tr>
<tr>
<td class="cantidad">2.00</td>
<td class="producto">KINDER DELICE</td>
<td class="precio">$10.00</td>
</tr>
<tr>
<td class="cantidad">1.00</td>
<td class="producto">COCA COLA 600 ML</td>
<td class="precio">$10.00</td>
</tr>
<tr>
<td class="cantidad"></td>
<td class="producto">TOTAL</td>
<td class="precio">$28.50</td>
</tr>
</tbody>
</table>
<p class="centrado">¡GRACIAS POR SU COMPRA!
<br>parzibyte.me</p>
</div>
</body>
</html>
Ahora nuestro ticket luce mejor, y puedes verlo aquí.
Imprimiendo
Lo único que falta es agregar una forma de imprimirlo. Sólo tenemos que llamar a window.print desde JS. Si deseamos que se imprima instantáneamente, lo haremos así:
window.print();
Imprimiendo al hacer click
Lo que recomiendo es que mejor pongamos un botón que lo imprima, porque si lo imprimimos al instante puede que no se hayan cargado las imágenes, o cosas así. De todos modos la elección queda en nosotros.
Vamos a agregar un botón:
<button class="oculto-impresion" onclick="imprimir()">Imprimir</button>
Y en el CSS vamos a ocultarlo, para que no salga al imprimir. Ya hice una entrada sobre esto aquí, por lo que no lo explicaré.
@media print {
.oculto-impresion,
.oculto-impresion * {
display: none !important;
}
}
Finalmente definimos la función en Javascript:
function imprimir() {
window.print();
}
Nuestro trabajo final se ve así.
Si hacemos click en el botón podemos ver que se imprime. Ahora simplemente tenemos que elegir la impresora y mandarlo.
Nota: puedes ocultar algunos elementos al imprimir, ya sea con CSS o con JavaScript y CSS.
Conclusión
Con esto podemos imprimir tickets y no sólo en la impresora térmica, también en cualquier otro dispositivo. Lo único de lo que debemos asegurarnos es de que nuestra impresora esté instalada correctamente.
Para dibujar los productos podemos hacerlo a mano, o con un framework como Vue, jQuery o AngularJS. Yo lo hice con javascript puro para hacerlo simple.
Si el ticket no funciona o no sale bien, podemos cambiar los pixeles y cualquier otra cosa. De esta manera podemos imprimir ticket en impresora térmica usando JavaScript
Recuerda: si quieres imprimir sin el diálogo de confirmación puede que quieras usar mi plugin.
veo que la opción de impresión window.print realiza una captura de pantalla, y es muy buena pero cuando son mas de 30 artículos queda a la mitad, o no se si yo lo estoy implementando mal.
Hola. Puede ser. Por eso prefiero enviar los comandos de manera nativa como se indica en: https://parzibyte.me/plugin-impresora-termica-v1/
Bro me sirvio de maravilla la idea para imprimir en el formato necesario en un hand held que viene con impresora térmica incluida, este tema me estaba matando pero con tu articulo logre integrar la idea a mi proyecto. Gracias!!!
Me agrada escuchar que haya funcionado.
Saludos!
Muy buen artículo, te agradezco porque explicas de manera simple cómo funciona. Quisiera saber cómo hago para que al dar en impimir() pueda guardar este archivo como pdf. Estoy en una mac y el cuadro de impresión de chrome dice “save as pdf” pero me sale por defecto un papel muy grande, quiero que salga un papel más pequeño para simular la generación del ticket real en pdf. Otra duda que tengo es cómo puedo saber cuantos píxeles de ancho son adecuados dependiendo del ancho del papel? es decir, explicaste que 8cm de ancho de papel, pero eso cuantos pixeles del CSS son? gracias
sirve para impresora ticket zebra el codigo gracias
Funciona para la mayoría de impresoras térmicas, pero si es impresora de etiquetas, no, ya que estas últimas no utilizan ESC POS hasta donde tengo entendido.
Saludos 🙂
disculpen mi ignorancia pero se puede imprimir desde un formato ya establecido en excel a la impresora ya instalada y pues si no es mucho pedir se podria mandar imprimir remotamente a una impresora termica portatil de 58 mm
Hola. Solo se puede con impresoras térmicas conectadas físicamente a la computadora; actualmente se puede solo en Windows en el navegador usando JavaScript.
Saludos
Hola, que tal?
He leido este post y me ha gustado mucho, me parecio tambien interesante, leí algunos comentarios ya que tengo un detalle y queria ver si alguno lo tenia, bueno el hecho es que al imprimirlo me imprime las letras muy pequeñas y deja mucho espacio en blanco, probe la solucion de cambiar los margenes, pero solo me funciono en chrome, para firefox no puedo hacer esta solucion, mi pregunta es ¿Hay alguna ottra manera de cambiar esos margenes de impresion?
Ya probe tambien com @page{margin: 0; }
Un saludo y gracias por el aporte 😀
De antemano gracias
Hola, he creado un plugin justamente para solucionar esos problemas; incluso evita el cuadro de impresión y puedes cortar el papel de forma nativa. https://parzibyte.me/blog/2019/08/01/imprimir-ticket-impresora-termica-javascript-plugin/
saludos a todos, desde hace un tiempo vengo suministrando a algunos clientes un sistema hecho en php, javascript css utilizando como navegador el firefox y de impresoras las pos58 de varias marcas tengo varios drivers, si el cliente no los tiene yo se los instalo y bueno todo iba bien uso igual un boton en mi vista de impresion que llama a la caja de dialogo de la impresora claro por ello no es una impresion directa, un comando de javascript llama al windows paraimprimir windows printer lo cierto es que ahora nose si es que los navegadores estan interfiriendo con la tipografia de la letra pero me imprime simbolos raros antes imprimia exactamente lo que estaba en la pagina como una imagen claro connfiguranado e navegador con nada, nada, nada, nada en configurar pagina y con 0 en los margenes , entonces quiero saber si alguno de ustedes les paso y como solucionaron o si esto ustedes tien una idea de resolverlo, es algo en el juego de caracteres no me lo interpreta como antes nose si es el driver pero antes funcionaba bien nose si es el navegador yo tengo la sospecha de ello que los navegadores mas actualed de firefox dejaron atras a los drivers de la impresoras termicas en fin si uno de ustedes me pueden ayudar muchas gracias
Hola, puedes usar el plugin de JavaScript, tal vez así se elimine tu problema: https://parzibyte.me/blog/2019/08/01/imprimir-ticket-impresora-termica-javascript-plugin/
recien veo este post y me parece interesante, pero el archivo script.js no lo encuntro cual seria?
Hola. Puedes ver la demostración aquí: https://parzibyte.github.io/ticket-js/3/
Y el script aquí: https://parzibyte.github.io/ticket-js/3/script.js
Hola, quiero saber si hay alguna manera de seleccionar la impresora predeterminada del lado del cliente. Tengo un aplicativo web que me imprime directamente desde php, pero necesito implementarlo y que al cliente imprimir lo haga por la impresora predeterminada al presionar un botón desde mi aplicativo php
Hola, no se puede seleccionar una impresora por defecto ni imprimir sin confirmación con JavaScript, debido a la seguridad.
Me parece que es posible hacerlo activando algunas banderas del navegador
Otra idea que se me ocurre es programar un plugin que se ejecute en las computadoras de los clientes (algo así como un ejecutable, .exe, que imprima usando un lenguaje de servidor); de esta manera sería posible y fácil. Si estás interesado en que lo haga, puedes contactarme: https://parzibyte.me/blog/contacto/
Hola Parzibyte, recién descubro tu web y tiene contenido muy útil, te agradezco por el trabajo que dedicas a ello! Quería consultarte algo, quiero mandar una impresión a una impresora térmica bluetooth, estoy abierto a posibilidades con PHP y javascript ya que creo que solo con PHP no es posible. Tendrás alguna entrada con algún ejemplo que pueda usar? O alguna recomendación para mi? Gracias de antemano!
Hola, gracias por tus comentarios 🙂
Sobre tu pregunta, no debería ser tan complejo mientras puedas imprimir desde la PC; es decir, si con Windows puedes, podrías imprimir desde JavaScript y otros lenguajes de programación.
Comienza instalando los drivers y después de eso debería funcionar como cualquier otra impresora. Saludos 🙂
Estoy usando bootstrap, y tengo un div con tus estilos, ¿por que no me respeta tus estilos aunque le ponga !important?
Hola. ¿Estás cargando la hoja de estilos después de Bootstrap? yo también he tenido problema con eso, así que te recomiendo que hagas la impresión en una página o documento html separado del resto, para que no haya mezcla de estilos
Saludos 🙂
Pero no imprime directo, me carga el controlador de impresoras de Windows, y toca dar otro enter. Hay forma que con js o java, se pueda directo?
Con Java tal vez sí, porque puede interactuar directamente con la impresora. Solo tendrías que programar la impresión al ticket con Java y llamar a ese servicio de Java con JavaScript
Hola parzibyte como vamos?, se me esta presentando un problema cuando imprimo, tengo instalado XAMPP ,estoy capturando cierta información en un formulario y lo guardo en mysql (en una base de datos); despues de capturar la informacion debe imprimir un recibo,la impresora me genera en ocasiones 2 o 3 recibos, en algunos casos de la misma persona con el mismo consecutivo y en otras ocasiones (que es lo mas delicado)con el consecutivo diferente.. esto me altera la contabilidad de los recibos. Al revisar en la base de datos aparecen datos duplicados con el consecutivo diferente. podría la impresora estar ocasionando dicho inconveniente? Que puedo estar haciendo mal?
Hola, no tendría nada que ver la impresora porque solamente se encarga de leer. Asegúrate de poner un autoincrementable en tu base de datos (no lo hagas manualmente), primero realiza todas las operaciones con tus datos y finalmente (en serio, hasta el final de todo) imprime los recibos.
En resumen, tal vez el problema sea la lógica; primero debes guardar los datos y finalmente imprimirlos
Hola, imprime pero la calidad es muy mala, que se puede hacer para mejorarla?
A veces hay que instalar los controladores no genéricos de la impresora para obtener mejor calidad
Buena tarde, he seguido tu tutorial y ha sido grandioso, pero tengo una duda, la impresora que utilizo es una xprinter pero no me imprime tu formato ni la imagen, espero tengas alguna solucion que me puedas proporcionar, gracias.
Hola, qué tal. Instala los drivers correctamente; yo también tengo una Xprinter (modelo POS-58) y va de maravilla. Saludos 🙂
buen dia
¿Funcionara con cualquier impresora térmica o hay algunas en especial?? ¿Cuál impresora usa usted ?
muchas gracias
Hola, funciona con la mayoría; pues todas hablan el “lenguaje” ESC/POS. Personalmente uso las Xprinter, aunque con las Epson y otros modelos funciona a la perfección
me quedó muy bien, solo le hice algunos cambios para que el botón aparezca cuando la orden está agregada a la base de datos, la tabla se va llenando cuando vas agregando productos pero está oculta con un hide() de jquery, te muestro algunas imágenes
este es mi botón:
Ticket
que solo aparece cuando doy agregar la orden o el carrito
este es el div donde se va llenando el ticket según se vallan agregando productos al carrito, pero el usuario nunca lo vé
Bajo Tierra
#1006
CANT
PRODUCTO
$$
¡GRACIAS POR SU COMPRA!
http://www.bajotierra.com
y esta es la función en jquery que manda la impresión
/* PRINT */
$(“#btn_print_ticket”).on(“click”,function(){
imprimir(“ticket”);
});
function imprimir(id) {
var data = document.getElementById(id).innerHTML;
var myWindow = window.open(”, ‘ticket’, ‘height=100,width=600’);
myWindow.document.write(‘Ticket Bajo Tierra’);
/*optional stylesheet*/
myWindow.document.write(“”);
myWindow.document.write(”);
// myWindow.document.write(“” + site_url + “assets/css/ticket.css”);
myWindow.document.write(data);
myWindow.document.write(”);
myWindow.document.close(); // necessary for IE >= 10
myWindow.onload = function () { // necessary if the div contain images
myWindow.focus(); // necessary for IE >= 10
myWindow.print();
myWindow.close();
};
}
/* END PRINT */
Hola. Es posible cambiar el tipo del tamaño de papel?. Que pasaría si el ticket es demasiado largo, sale en una sola?
Sí, el ticket sale en tamaño completo tanto a lo ancho como a lo largo, y mientras haya papel no pasa nada. De todos modos, puedes probar por ti mismo imprimiendo uno de prueba. Saludos
Me sorprende la rapidez en responder.
Te comento que mi ticket lo hice en php creando un archivo .txt e imprimia con php, pero eso era en un proyecto local, pero ahora necesito que varios clientes puedan hacer ventas, pero la opcion de imprimir por php ya no es factible.
Aun sigo creando el ticket.txt pero ahora le doy lectura por javascript, toca probar como imprime por el browser.
Mil gracias por responder.
Ya he escrito un post sobre cómo imprimirlo en Javascript del lado del cliente: https://parzibyte.me/blog/2017/10/17/imprimir-ticket-en-impresora-termica-usando-javascript/
Prueba y a ver qué tal. Saludos.
Hola parzibyte, que buen post… yo tengo el siguiente dilema… instale un servidor xampp en el cual accedo local mente: localhost/ejemplo/index.html
tengo un formulario que captura información y a la vez imprime en una impresora térmica de tickets como explicas en el post anterior.
Puedo acceder desde otro equipo en la red y capturar la información con el formulario //ip-servidorlocal/ejemplo/index.html ; mas no se como imprimir teniendo la impresora de tickets instalada en otro equipo.. desde el servidor funciona correctamente. de antemano mil gracias…
Gracias por tus comentarios 🙂
Respondiendo a tu pregunta: la impresora debe estar conectada físicamente al servidor en donde quieres imprimir si quieres imprimir localmente. Si no tienes la posibilidad de instalar XAMPP en la PC que me dices, intenta usar el método de JavaScript
Que tal, imprimi la página que tu realizaste pero me sale con mucho margen, especialmente el margen inferior es muy grande te adjunto la imagen donde puedes verlo: https://imgur.com/a/0ZAG9Ku
De que forma puedo solucionarlo? Gracias!
Hola. No sé cuál navegador utilizas, pero te recomiendo utilizar Chrome, pues trae más opciones de configuración. En caso de que lo estés utilizando, al momento de imprimir haz click en Más opciones. Ahí, en Márgenes elige Ninguno, y modifica si quieres la escala. La ventaja de Chrome es que permite modificar márgenes y da una vista previa.
Prueba y a ver qué sale.
Buenas tardes amigo, gracias por tu aporte. Tengo una duda como hago para que la impresora corte la impresión?
es una BIXOLON SRP-F312 solo que al terminar la ultima linea no corta la impresión!
Primero verifica que tu impresora tenga soporte para cortar, y que los controladores estén instalados correctamente.
Después, en el panel de control de Windows (o el equivalente en el sistema operativo que utilices) configura la impresora para que corte siempre al terminar de imprimir.
No siempre funciona, y esa es la desventaja de utilizar Javascript, pero puedes intentarlo.
hola mi estimado porfavor puedes detallar un poco mas sobre la imrpesion directa sin utilizar el boton
“”window.print desde JS”” no logro captar la idea muchas gracias de antemano
Hola, qué tal.
Si queremos hacerlo sin botón, es decir, que al abrir la página se imprima, puedes hacerlo en el evento onload, algo así:
window.onload = function(){
window.print();
}
De esta forma, tan pronto cargue la ventana se imprimirá automáticamente.
Amigo, buen post
Solo una pregunta, lo que busco es que mi ticket se imprima directamente solo con pasarle el nombre de la impresora, es decir, que no de la opcion de seleccionar la impresora.
Es posible eso?
Saludos
Hola, es imposible debido a la seguridad de la web. Si eso fuera posible, imagina, un usuario malicioso podría mandar a tu impresora 1000 impresiones, sin que tú confirmes nada. Claro que no sería algo de seguridad, pero sería molesto. Lo que puedes hacer es activar algunas banderas dependiendo del navegador, imprimir con un lenguaje del lado del servidor como PHP o utilizar algo como Electron que permite imprimir silenciosamente desde Javascript.
Un saludo.
Con php no se puede imprimir desde un hosting a una impresora que tengo en mi casa
Eso sí se puede. Configura tu módem para abrir el puerto 80 que es por defecto de Apache (si usas otro, utiliza ese puerto), asigna ese puerto a la ip de la computadora en donde estará la impresora. Luego, consigue tu dirección ip pública en un sitio como iplocationfinder.com y finalmente para imprimir desde cualquier lugar accede al archivo que imprime como si estuvieras en tu computadora. Es decir, si en tu computadora imprimes en localhost/imprimir.php entonces (suponiendo que tu ip es 66.33.22.55) para imprimir desde cualquier lugar podrías ir a 66.33.22.55/imprimir.php
Un saludo
Buenas tardes! Yo tengo una página web en PHP en un servidor web. Quería saber como puedo hacer para que mi cliente pueda acceder al sitio desde su casa e imprimir en su PC.
Hola. La impresora debe estar conectada físicamente al servidor y en este caso el servidor debería ser la pc de tu cliente. Te recomiendo que mejor lo imprimas del lado del cliente con JavaScript. Saludos 🙂
https://parzibyte.me/blog/2017/10/17/imprimir-ticket-en-impresora-termica-usando-javascript/
Imprime eso pero con un monton de espacio en blanco debajo del contenido…. como haces para que solo imprima lo que se pone y lo corte ahi nomas que termina el contenido?
Seguramente el espacio en blanco es debido a que intenta imprimir una imagen pero no puede, y deja todo el espacio vacío.
quita el encabezado y pie de pagina desde la configuración de impresión
lo que te está pasando es por el tamaño que estás poniendo a tu configuración de impresora, a mi me sucede lo mismo y es por eso, pero eso no se puede al menos no se cómo se podría modificar el tamaño de la hoja desde javascript para que la impresora tome el tamaño de la hoja según el tamaó de lo que se está enviando en la lista, si alguien lo sabe que pase el tip
En Chrome (y supongo que en sus hermanos) existe la opción de cambiar los márgenes y la escala. Con eso se puede imprimir y aprovechar la mayor cantidad de papel
El error de la impresión, que te salga un tramo muy largo y en blanco es por la configuracion de la impresión en google chrome, solo imprime normal y antes de imprimir dale click en mas opciones y se desglosara otras opciones, en donde dice tamaño de papel pon la opción de “58(48) x297mm” e imprime, ya imprimirá bien, si no llegase a actualizar la vista previa al imprimir, no importa aun asi imprimirá bien, solo es cambiar el tamaño del papel