Chat

A continuación comparto un ejemplo de interfaz de usuario para un chat, utilizando HTML y CSS. El código aplica buenas prácticas de accesibilidad, como el uso de atributos aria-* y role, así como el uso de etiquetas semánticas.

Además, entre sus características se encuentran:

  • Se sombrea la parte superior cuando hay un historial de mensajes con el fin de informar al usuario que puede desplazarse hacia arriba.
  • Se respeta que el mensaje “Te responderemos tan pronto como sea posible” se mantenga en una línea, y que el texto sobrante se oculte con puntos suspensivos.
  • Nomenclatura BEM para los nombres de las clases.
  • Variables CSS para los colores, fuentes y espaciados.
  • Dibujo de los bocadillos de los mensajes con solo CSS.
  • El input de texto crece con el contenido.
  • Anidamiento de los bloques CSS para que no se apliquen estilos a los elementos de otros componentes.
  • El contenedor de mensajes tiene un atributo aria-live="polite", para que los lectores de pantalla anuncien los nuevos mensajes.

Demo

Código

<section class="chat">
    <header class="chat__header">
        <button class="button chat__close" aria-label="Cerrar">✖️</button>
        <h2 class="chat__name">Soporte técnico</h2>
        <p class="chat__status">
            <span class="chat__led"></span>
            Te responderemos tan pronto como sea posible.
        </p>
    </header>
    <!-- Contenedor de mensajes -->
    <div class="chat__messages" aria-live="polite">
        <!-- Componente de mensaje receptor -->
        <article class="message message--receptor">
            <h3 class="message__username">Caballero blanca luna</h3>
            <p class="message__text">
                Tortor vitae purus faucibus ornare. Velit euismod in pellentesque massa placerat duis ultricies lacus sed turpis tincidunt id aliquet risus feugiat in ante metus, dictum at tempor commodo, ullamcorper a?
            </p>
        </article>
        <!-- Componente de mensaje emisor -->
        <article class="message message--emisor">
            <h3 class="message__username">Don Quijote</h3>
            <p class="message__text">
                Quis ipsum suspendisse ultrices gravida dictum fusce ut placerat orci nulla pellentesque dignissim.
            </p>
        </article>
    </div>
    <footer class="chat__footer">
        <form class="chat__form">
            <!-- Input que crece con el texto -->
            <div
                role="textbox"
                aria-label="Nuevo mensaje"
                aria-placeholder="Escribe tu mensaje..."
                contenteditable="true"
                class="chat__input"
                name="mensaje"
            ></div>
            <!-- Botones con funciones secundarias -->
            <button type="button" class="button chat__button" aria-label="Abrir emojis">😀</button>
            <button type="button" class="button chat__attachment" aria-label="Adjuntar archivo">📎</button>
        </form>
    </footer>
</section>
:root {
    /* Colors */
    --color-black: #1D1E21;
    --color-white: #FFF;
    --color-background: #E8E8E8;
    --color-green: #43B72A;

    /* Fonts */
    --font-body: Arial;

    /* Gaps */
    --gap-s: 0.9rem;
    --gap-m: 1rem;
    --gap-l: 1.5rem;
    --gap-xl: 2rem;
    --gap-xxl: 3rem;
}

/* Animaciones */
@keyframes ani-pulse {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

/* Generales */

body {
    font-family: var(--font-body);
}

/* Componentes */

.button {
    display: inline-block;
    background-color: initial;
    border: 0;
    padding: var(--gap-s);
    min-width: var(--gap-l);
}

/* Chat */

.chat {
    position: fixed;
    bottom: 0;
    right: var(--gap-xxl);
    width: 20rem;
    background-color: var(--color-white);
    border-top-left-radius: var(--gap-l);
    border-top-right-radius: var(--gap-l);
    .chat__header {
        background-color: var(--color-black);
        color: var(--color-white);
        border-top-left-radius: var(--gap-l);
        border-top-right-radius: var(--gap-l);
        padding: var(--gap-m);
        box-sizing: border-box;
        position: relative;
        &::after {
            content: "";
            position: absolute;
            left: 0;
            right: 0;
            bottom: -2rem;
            height: 2rem;
            background-image: linear-gradient(var(--color-background), transparent);
            z-index: 10;
        }
    }
    .chat__close {
        display: block;
        margin-left: auto;
    }
    .chat__name {
        margin: 0;
        font-size: var(--gap-l);
        font-weight: normal;
        margin-bottom: .4rem;
    }
    .chat__status {
        margin: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        &:hover {
            white-space: initial;
            overflow: initial;
            text-overflow: initial;
        }
    }
    .chat__led {
        --size: .6rem;
        display: inline-block;
        width: var(--size);
        height: var(--size);
        border-radius: 50%;
        background-color: var(--color-green);
        animation-name: ani-pulse;
        animation-duration: 1s;
        animation-iteration-count: infinite;
        animation-direction: alternate;
    }

    .chat__messages {
        height: 20rem;
        padding-inline: var(--gap-s);
        overflow-y: auto;
        background-color: var(--color-background);
    }

    .message {
        width: 14rem;
        background-color: var(--color-green);
        padding: var(--gap-m);
        margin-block: var(--gap-l);
        border-radius: var(--gap-s);
        position: relative;
        margin-left: auto;
        &::before {
            --lado: 0;
            display: block;
            content: "";
            width: var(--lado);
            height: var(--lado);
            position: absolute;
            bottom: -12px;
            right: 1rem;
            transform: rotate(-136deg);
            border: 1rem solid var(--color-green);
            border-left-color: transparent;
            border-bottom-color: transparent;
            border-right-color: transparent;
    }
    .message__username {
        font-weight: normal;
        margin: 0;
        font-size: var(--gap-m);
        color: var(--color-white);
    }
    .message__text {
        margin: 0;
        margin-top: var(--gap-s);
        font-size: var(--gap-s);
    }
    }
    .message--receptor {
        margin-left: initial;
        &::before {
            right: 0;
            left: 1rem;
            transform: rotate(275deg);
            bottom: -16px;
        }
    }

    .chat__footer {
        .chat__form {
            display: flex;
            align-items: flex-end;
        }
        .chat__input {
            border: 0;
            background-color: initial;
            width: 100%;
            padding: var(--gap-s);
            max-height: 5rem;
            overflow-y: auto;
            &:focus {
                outline: none;
            }
            &:empty::before {
                position: absolute;
                content: "Escribe tu mensaje...";
            }
        }
    }
}