50% OFF Plus
--:--:--
¡Obtener!

Modificación de elementos DOM

Avanzado
JavaScript
JavaScript
Actualizado: 16/05/2025

¡Desbloquea el curso de JavaScript completo!

IA
Ejercicios
Certificado
Entrar

Mira la lección en vídeo

Accede al vídeo completo de esta lección y a más contenido exclusivo con el Plan Plus.

Desbloquear Plan Plus

Alteración de contenido textual: Diferencias entre innerText, textContent y nodeValue

Cuando trabajamos con el DOM, modificar el contenido textual de los elementos es una operación fundamental. JavaScript ofrece tres propiedades principales para manipular texto en elementos: innerText, textContent y nodeValue. Aunque parecen similares, cada una tiene comportamientos específicos que debemos entender para elegir la más adecuada en cada situación.

innerText

La propiedad innerText representa el contenido de texto visible de un elemento, similar a lo que un usuario vería en la página. Esta propiedad:

  • Respeta el estilo CSS aplicado (no muestra elementos ocultos con display: none)
  • Aplica formato básico respetando saltos de línea
  • Es sensible al rendimiento, ya que desencadena un recálculo de estilos
// Obtener el texto visible
const heading = document.querySelector('h1');
const visibleText = heading.innerText;

// Modificar el texto visible
heading.innerText = 'New Heading Text';

// innerText ignora elementos ocultos
const div = document.querySelector('div');
div.innerHTML = 'Visible <span style="display: none">Hidden</span> Text';
console.log(div.innerText); // Output: "Visible Text"

textContent

La propiedad textContent representa todo el contenido textual de un nodo y sus descendientes, independientemente de su visibilidad. Esta propiedad:

  • Devuelve el contenido de todos los elementos, incluso los ocultos con CSS
  • Preserva espacios en blanco y formato original del código HTML
  • Tiene mejor rendimiento que innerText al no provocar recálculos de estilo
// Obtener todo el contenido textual
const paragraph = document.querySelector('p');
const allText = paragraph.textContent;

// Modificar todo el contenido textual
paragraph.textContent = 'This replaces all content, including nested elements';

// textContent incluye elementos ocultos
const div = document.querySelector('div');
div.innerHTML = 'Visible <span style="display: none">Hidden</span> Text';
console.log(div.textContent); // Output: "Visible Hidden Text"

nodeValue

La propiedad nodeValue es diferente a las anteriores y funciona a un nivel más bajo del DOM. Esta propiedad:

  • Solo funciona en nodos de texto, comentarios o atributos (no directamente en elementos)
  • Requiere acceder primero al nodo de texto específico
  • Es más precisa cuando necesitamos manipular un nodo de texto específico
// Para usar nodeValue, primero debemos acceder al nodo de texto
const paragraph = document.querySelector('p');
const textNode = paragraph.firstChild;

// Solo funciona si firstChild es un nodo de texto
if (textNode && textNode.nodeType === Node.TEXT_NODE) {
    console.log(textNode.nodeValue); // Muestra el contenido del nodo de texto
    textNode.nodeValue = 'Modified text content';
}

Comparación práctica

Veamos un ejemplo que ilustra las diferencias entre estas propiedades:

// Creamos un elemento con contenido mixto
const container = document.createElement('div');
container.innerHTML = `
    Visible text
    <span style="display: none">Hidden text</span>
    <script>const x = 1;</script>
`;

console.log(container.innerText);    // "Visible text"
console.log(container.textContent);  // "Visible text\n    Hidden text\n    const x = 1;"

// Para nodeValue necesitamos el nodo de texto específico
const firstTextNode = container.firstChild;
console.log(firstTextNode.nodeValue); // "\n    Visible text\n    "

Escenarios de uso recomendados

  • Usa innerText cuando necesites obtener o establecer el texto visible tal como aparece en la página.
  • Usa textContent cuando necesites todo el contenido textual sin importar la visibilidad, o por razones de rendimiento.
  • Usa nodeValue cuando necesites manipular con precisión un nodo de texto específico dentro de un elemento.

Consideraciones de seguridad

A diferencia de innerHTML, estas tres propiedades tratan el contenido como texto plano, lo que las hace seguras contra ataques XSS (Cross-Site Scripting):

// Seguro: el código HTML se muestra como texto, no se ejecuta
const userInput = '<script>alert("XSS Attack")</script>';
element.textContent = userInput; // Se muestra como texto: <script>alert("XSS Attack")</script>

La elección entre estas propiedades dependerá del contexto específico de tu aplicación y de si necesitas preservar o ignorar elementos ocultos, mantener o eliminar formato, o manipular nodos de texto específicos.

Gestión de atributos personalizados y dataset: Almacenamiento de metadatos en elementos

Los elementos HTML no solo contienen contenido visible, sino que también pueden almacenar metadatos adicionales que enriquecen su funcionalidad sin afectar su presentación. JavaScript ofrece mecanismos para gestionar estos datos a través de atributos personalizados y la interfaz dataset, permitiéndonos asociar información relevante directamente a los elementos del DOM.

Atributos estándar vs personalizados

Los elementos HTML tienen atributos estándar como id, class o src, pero a menudo necesitamos almacenar información adicional específica para nuestra aplicación:

// Acceso a atributos estándar
const link = document.querySelector('a');
console.log(link.href);         // https://example.com
console.log(link.getAttribute('href')); // https://example.com

// Modificación de atributos estándar
link.href = 'https://mozilla.org';
// Alternativa:
link.setAttribute('href', 'https://mozilla.org');

Para información personalizada, podemos usar atributos personalizados que siguen la convención data-*:

<button data-role="submit" data-user-id="123" data-permission="admin">
  Enviar formulario
</button>

Manipulación de atributos con getAttribute y setAttribute

Los métodos getAttribute() y setAttribute() permiten trabajar con cualquier tipo de atributo, incluyendo los personalizados:

const button = document.querySelector('button');

// Lectura de atributos personalizados
const role = button.getAttribute('data-role');        // "submit"
const userId = button.getAttribute('data-user-id');   // "123"

// Modificación de atributos personalizados
button.setAttribute('data-status', 'pending');
button.setAttribute('data-user-id', '456');

// Verificación de existencia de atributos
const hasPermission = button.hasAttribute('data-permission'); // true

// Eliminación de atributos
button.removeAttribute('data-status');

La interfaz dataset: acceso simplificado

La propiedad dataset proporciona una forma más elegante y directa de acceder a los atributos data-*, convirtiéndolos automáticamente en propiedades de un objeto JavaScript:

const button = document.querySelector('button');

// Acceso a través de dataset (notación camelCase)
console.log(button.dataset.role);        // "submit"
console.log(button.dataset.userId);      // "123" (data-user-id se convierte a camelCase)
console.log(button.dataset.permission);  // "admin"

// Modificación a través de dataset
button.dataset.status = 'processing';
button.dataset.timestamp = Date.now();

// Eliminación de atributos data
delete button.dataset.status;

Observa cómo los nombres de atributos con guiones (data-user-id) se convierten automáticamente a camelCase (dataset.userId).

Casos de uso prácticos

Los atributos personalizados y dataset son especialmente útiles para:

  • Almacenar identificadores relacionados con datos de backend:
// Lista de productos con IDs para operaciones AJAX
const productList = document.querySelector('.products');

productList.addEventListener('click', (event) => {
  if (event.target.matches('.product')) {
    const productId = event.target.dataset.productId;
    fetchProductDetails(productId);
  }
});
  • Configuración de componentes sin necesidad de JavaScript adicional:
<div class="carousel" data-auto-play="true" data-interval="5000" data-show-indicators="false">
  <!-- Contenido del carrusel -->
</div>
// Inicialización basada en atributos data
document.querySelectorAll('.carousel').forEach(carousel => {
  new Carousel(carousel, {
    autoPlay: carousel.dataset.autoPlay === 'true',
    interval: parseInt(carousel.dataset.interval || 3000),
    showIndicators: carousel.dataset.showIndicators !== 'false'
  });
});
  • Estado de la interfaz de usuario para elementos interactivos:
const toggleButton = document.querySelector('.toggle-button');

toggleButton.addEventListener('click', () => {
  // Cambiar entre estados usando dataset
  if (toggleButton.dataset.state === 'active') {
    toggleButton.dataset.state = 'inactive';
    toggleButton.textContent = 'Activar';
  } else {
    toggleButton.dataset.state = 'active';
    toggleButton.textContent = 'Desactivar';
  }
});

Consideraciones importantes

  • Los valores en dataset siempre se almacenan como cadenas de texto. Para valores numéricos o booleanos, necesitarás realizar la conversión:
// Conversión de tipos al leer valores
const count = parseInt(element.dataset.count, 10);
const isEnabled = element.dataset.enabled === 'true';
const config = JSON.parse(element.dataset.config || '{}');
  • Los atributos data-* son visibles en el HTML, por lo que no son adecuados para información sensible.

  • Los cambios en dataset se reflejan inmediatamente en el DOM y viceversa:

// Los cambios son bidireccionales
element.dataset.status = 'active';
console.log(element.getAttribute('data-status')); // "active"

element.setAttribute('data-priority', 'high');
console.log(element.dataset.priority); // "high"
  • Puedes usar atributos personalizados como selectores CSS:
/* Estilizar elementos basados en atributos data */
button[data-role="submit"] {
  background-color: green;
}

.product[data-stock="0"] {
  opacity: 0.5;
}

Los atributos personalizados y la interfaz dataset proporcionan una forma estructurada y semántica de asociar metadatos a elementos DOM, facilitando la creación de interfaces dinámicas sin necesidad de mantener estados separados en variables JavaScript. Estrategtas para cambios visuales dinámicos

AI:

Manipulación de cly estilos: Estratestas para cambios visuales dinámicos

Guarda tu progreso

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

La manipulación de clases y estilos es fundamental para crear interfaces dinámicas y responsivas. JavaScript ofrece varias formas de modificar la apariencia de los elementos HTML, cada una con sus propias ventajas.

Manipulación de clases CSS

La interfaz classList proporciona métodos poderosos para gestionar las clases CSS de un elemento, ofreciendo una alternativa más limpia y eficiente que manipular directamente el atributo className.

const card = document.querySelector('.card');

// Añadir clases
card.classList.add('highlighted', 'active');

// Eliminar clases
card.classList.remove('disabled');

// Alternar clases (añade si no existe, elimina si existe)
card.classList.toggle('expanded');

// Verificar si un elemento tiene una clase específica
if (card.classList.contains('editable')) {
  enableEditMode();
}

// Reemplazar una clase por otra
card.classList.replace('loading', 'loaded');

La interfaz classList es más eficiente que manipular directamente className, ya que evita tener que parsear y reconstruir cadenas de texto:

// Enfoque antiguo (menos recomendado)
if (!element.className.includes('active')) {
  element.className += ' active';
}

// Enfoque moderno con classList (recomendado)
element.classList.add('active');

Manipulación directa de estilos

Para cambios de estilo específicos, podemos acceder directamente a la propiedad style del elemento:

const notification = document.querySelector('.notification');

// Establecer estilos individuales
notification.style.backgroundColor = '#e74c3c';
notification.style.color = 'white';
notification.style.transform = 'translateY(-20px)';
notification.style.transition = 'all 0.3s ease';

// Las propiedades CSS con guiones se convierten a camelCase
notification.style.borderRadius = '4px';
notification.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)';

Esta técnica es ideal para cambios dinámicos basados en interacciones del usuario o datos variables:

// Cambiar el ancho de una barra de progreso basado en un porcentaje
function updateProgressBar(percent) {
  const progressBar = document.querySelector('.progress-bar');
  progressBar.style.width = `${percent}%`;
  
  // Cambiar color basado en el progreso
  if (percent < 30) {
    progressBar.style.backgroundColor = '#e74c3c'; // rojo
  } else if (percent < 70) {
    progressBar.style.backgroundColor = '#f39c12'; // naranja
  } else {
    progressBar.style.backgroundColor = '#2ecc71'; // verde
  }
}

Aplicando múltiples estilos

Para aplicar varios estilos a la vez, podemos usar cssText o la API Object.assign():

// Usando cssText para múltiples estilos
element.style.cssText = 'color: white; background-color: #3498db; padding: 10px; border-radius: 4px;';

// Alternativa usando Object.assign()
Object.assign(element.style, {
  display: 'flex',
  justifyContent: 'center',
  alignItems: 'center',
  height: '200px',
  backgroundColor: '#9b59b6'
});

Accediendo a estilos computados

Para obtener los estilos actuales aplicados a un elemento (incluyendo los de hojas de estilo):

const element = document.querySelector('.box');
const styles = window.getComputedStyle(element);

console.log(styles.backgroundColor);
console.log(styles.fontSize);
console.log(styles.getPropertyValue('margin-left'));

// Para pseudo-elementos
const beforeStyles = window.getComputedStyle(element, '::before');
console.log(beforeStyles.content);

Estrategias para animaciones y transiciones

Las transiciones CSS combinadas con JavaScript ofrecen una forma eficiente de crear animaciones:

function animateElement() {
  const box = document.querySelector('.box');
  
  // Configurar la transición antes de cambiar propiedades
  box.style.transition = 'transform 0.5s ease-out, opacity 0.5s ease';
  
  // Aplicar los cambios que activarán la transición
  box.style.transform = 'scale(1.2) rotate(5deg)';
  box.style.opacity = '0.8';
  
  // Restaurar después de la transición
  setTimeout(() => {
    box.style.transform = 'scale(1) rotate(0)';
    box.style.opacity = '1';
  }, 2000);
}

Clases vs. estilos inline: ¿Cuándo usar cada uno?

  • Uso de clases CSS (recomendado para la mayoría de casos):
  • Para cambios que afectan múltiples propiedades
  • Cuando los estilos están predefinidos
  • Para mantener la separación de responsabilidades
// Cambiar entre estados visuales predefinidos
function toggleDarkMode() {
  document.body.classList.toggle('dark-theme');
  
  // También podemos actualizar elementos hijos
  document.querySelectorAll('.card').forEach(card => {
    card.classList.toggle('dark-card');
  });
  
  // Guardar preferencia del usuario
  const isDarkMode = document.body.classList.contains('dark-theme');
  localStorage.setItem('darkMode', isDarkMode);
}
  • Uso de estilos inline:
  • Para valores calculados dinámicamente
  • Para animaciones y cambios temporales
  • Cuando necesitas precisión absoluta
// Posicionar un tooltip relativo a un elemento
function showTooltip(targetElement, text) {
  const tooltip = document.createElement('div');
  tooltip.className = 'tooltip';
  tooltip.textContent = text;
  document.body.appendChild(tooltip);
  
  const rect = targetElement.getBoundingClientRect();
  tooltip.style.left = `${rect.left + rect.width / 2 - tooltip.offsetWidth / 2}px`;
  tooltip.style.top = `${rect.bottom + 10}px`;
  
  // Mostrar con animación
  tooltip.style.opacity = '0';
  tooltip.style.transform = 'translateY(-10px)';
  tooltip.style.transition = 'all 0.3s ease';
  
  // Forzar reflow para que la transición funcione
  tooltip.offsetHeight;
  
  tooltip.style.opacity = '1';
  tooltip.style.transform = 'translateY(0)';
}

Técnicas avanzadas: Variables CSS (propiedades personalizadas)

Las variables CSS combinadas con JavaScript permiten crear temas dinámicos y sistemas de diseño flexibles:

// Cambiar tema de color usando variables CSS
function setThemeColor(primaryColor, secondaryColor) {
  document.documentElement.style.setProperty('--primary-color', primaryColor);
  document.documentElement.style.setProperty('--secondary-color', secondaryColor);
  
  // Guardar preferencias
  localStorage.setItem('theme', JSON.stringify({ primary: primaryColor, secondary: secondaryColor }));
}

// Ejemplo de uso
document.querySelector('#theme-selector').addEventListener('change', (e) => {
  const theme = e.target.value;
  
  if (theme === 'blue') {
    setThemeColor('#3498db', '#2980b9');
  } else if (theme === 'green') {
    setThemeColor('#2ecc71', '#27ae60');
  } else if (theme === 'purple') {
    setThemeColor('#9b59b6', '#8e44ad');
  }
});

Optimización del rendimiento

Al manipular estilos, es importante considerar el rendimiento:

  • Minimiza los reflows: Agrupa los cambios de estilo para reducir recálculos de layout
// Mal (causa múltiples reflows)
element.style.width = '100px';
element.style.height = '100px';
element.style.margin = '10px';

// Mejor (un solo reflow)
element.style.cssText = 'width: 100px; height: 100px; margin: 10px;';

// O usando clases (aún mejor)
element.classList.add('box-dimensions');
  • Usa requestAnimationFrame para animaciones suaves:
function animateProgress(element, targetWidth) {
  let width = 0;
  
  function step() {
    width += 2;
    element.style.width = `${width}%`;
    
    if (width < targetWidth) {
      requestAnimationFrame(step);
    }
  }
  
  requestAnimationFrame(step);
}

// Uso
animateProgress(document.querySelector('.progress-bar'), 75);

Ejemplo práctico: Sistema de notificaciones

Combinando clases y estilos para crear un sistema de notificaciones dinámico:

function showNotification(message, type = 'info') {
  const notification = document.createElement('div');
  notification.className = 'notification';
  notification.classList.add(`notification-${type}`);
  notification.textContent = message;
  
  // Añadir al DOM
  document.body.appendChild(notification);
  
  // Forzar reflow antes de añadir clase para activar transición
  notification.offsetHeight;
  
  // Mostrar con animación
  notification.classList.add('notification-visible');
  
  // Configurar auto-cierre
  setTimeout(() => {
    notification.classList.remove('notification-visible');
    
    // Eliminar del DOM después de la transición
    notification.addEventListener('transitionend', () => {
      notification.remove();
    });
  }, 5000);
  
  // Añadir botón de cierre
  const closeBtn = document.createElement('button');
  closeBtn.className = 'notification-close';
  closeBtn.innerHTML = '&times;';
  closeBtn.addEventListener('click', () => {
    notification.classList.remove('notification-visible');
  });
  
  notification.appendChild(closeBtn);
  
  return notification;
}

// Ejemplos de uso
document.querySelector('#success-btn').addEventListener('click', () => {
  showNotification('Operación completada con éxito', 'success');
});

document.querySelector('#error-btn').addEventListener('click', () => {
  showNotification('Ha ocurrido un error', 'error');
});

Con el CSS correspondiente:

.notification {
  position: fixed;
  bottom: -100px;
  right: 20px;
  padding: 15px 20px;
  border-radius: 4px;
  box-shadow: 0 3px 10px rgba(0,0,0,0.2);
  transition: transform 0.3s ease, opacity 0.3s ease;
  opacity: 0;
  transform: translateY(0);
}

.notification-visible {
  transform: translateY(-120px);
  opacity: 1;
}

.notification-info {
  background-color: #3498db;
  color: white;
}

.notification-success {
  background-color: #2ecc71;
  color: white;
}

.notification-error {
  background-color: #e74c3c;
  color: white;
}

Esta combinación de manipulación de clases y estilos permite crear interfaces dinámicas y responsivas que mejoran significativamente la experiencia del usuario.

AI:

Manipulación de clases y estilos: Estrategias para cambios visuales dinámicos

La manipulación de clases y estilos es una habilidad fundamental para crear interfaces web dinámicas y responsivas. JavaScript ofrece diferentes mecanismos para modificar la apariencia de los elementos HTML, cada uno con sus propias ventajas según el contexto de uso.

Manipulación de clases con classList

La interfaz classList proporciona métodos intuitivos para gestionar las clases CSS de un elemento, ofreciendo una alternativa más limpia que manipular directamente el atributo className:

const card = document.querySelector('.card');

// Añadir una o más clases
card.classList.add('highlighted', 'active');

// Eliminar clases
card.classList.remove('disabled');

// Alternar una clase (añade si no existe, elimina si existe)
card.classList.toggle('expanded');

// Verificar si un elemento tiene una clase específica
if (card.classList.contains('editable')) {
  enableEditMode();
}

// Reemplazar una clase por otra
card.classList.replace('loading', 'loaded');

Esta API es más eficiente que manipular directamente className, ya que evita tener que parsear y reconstruir cadenas de texto:

// Enfoque antiguo (menos recomendado)
if (!element.className.includes('active')) {
  element.className += ' active';
}

// Enfoque moderno con classList (recomendado)
element.classList.add('active');

Manipulación directa de estilos inline

Para cambios de estilo específicos, podemos acceder a la propiedad style del elemento:

const notification = document.querySelector('.notification');

// Establecer estilos individuales
notification.style.backgroundColor = '#e74c3c';
notification.style.color = 'white';
notification.style.transform = 'translateY(-20px)';

// Las propiedades CSS con guiones se convierten a camelCase
notification.style.borderRadius = '4px';
notification.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)';

Esta técnica es ideal para cambios dinámicos basados en interacciones del usuario o datos variables:

// Cambiar el ancho de una barra de progreso según un porcentaje
function updateProgressBar(percent) {
  const progressBar = document.querySelector('.progress-bar');
  progressBar.style.width = `${percent}%`;
  
  // Cambiar color basado en el progreso
  if (percent < 30) {
    progressBar.style.backgroundColor = '#e74c3c'; // rojo
  } else if (percent < 70) {
    progressBar.style.backgroundColor = '#f39c12'; // naranja
  } else {
    progressBar.style.backgroundColor = '#2ecc71'; // verde
  }
}

Aplicando múltiples estilos

Para aplicar varios estilos a la vez, podemos usar cssText o la API Object.assign():

// Usando cssText para múltiples estilos
element.style.cssText = 'color: white; background-color: #3498db; padding: 10px;';

// Alternativa usando Object.assign()
Object.assign(element.style, {
  display: 'flex',
  justifyContent: 'center',
  alignItems: 'center',
  height: '200px',
  backgroundColor: '#9b59b6'
});

Accediendo a estilos computados

Para obtener los estilos actuales aplicados a un elemento (incluyendo los de hojas de estilo):

const element = document.querySelector('.box');
const styles = window.getComputedStyle(element);

console.log(styles.backgroundColor);
console.log(styles.fontSize);
console.log(styles.getPropertyValue('margin-left'));

// Para pseudo-elementos
const beforeStyles = window.getComputedStyle(element, '::before');
console.log(beforeStyles.content);

Estrategias para animaciones y transiciones

Las transiciones CSS combinadas con JavaScript ofrecen una forma eficiente de crear animaciones:

function animateElement() {
  const box = document.querySelector('.box');
  
  // Configurar la transición antes de cambiar propiedades
  box.style.transition = 'transform 0.5s ease-out, opacity 0.5s ease';
  
  // Aplicar los cambios que activarán la transición
  box.style.transform = 'scale(1.2) rotate(5deg)';
  box.style.opacity = '0.8';
  
  // Restaurar después de la transición
  setTimeout(() => {
    box.style.transform = 'scale(1) rotate(0)';
    box.style.opacity = '1';
  }, 2000);
}

Clases vs. estilos inline: ¿Cuándo usar cada uno?

  • Uso de clases CSS (recomendado para la mayoría de casos):
  • Para cambios que afectan múltiples propiedades
  • Cuando los estilos están predefinidos
  • Para mantener la separación de responsabilidades
// Cambiar entre estados visuales predefinidos
function toggleDarkMode() {
  document.body.classList.toggle('dark-theme');
  
  // También podemos actualizar elementos hijos
  document.querySelectorAll('.card').forEach(card => {
    card.classList.toggle('dark-card');
  });
  
  // Guardar preferencia del usuario
  const isDarkMode = document.body.classList.contains('dark-theme');
  localStorage.setItem('darkMode', isDarkMode);
}
  • Uso de estilos inline:
  • Para valores calculados dinámicamente
  • Para animaciones y cambios temporales
  • Cuando necesitas precisión absoluta
// Posicionar un tooltip relativo a un elemento
function showTooltip(targetElement, text) {
  const tooltip = document.createElement('div');
  tooltip.className = 'tooltip';
  tooltip.textContent = text;
  document.body.appendChild(tooltip);
  
  const rect = targetElement.getBoundingClientRect();
  tooltip.style.left = `${rect.left + rect.width / 2 - tooltip.offsetWidth / 2}px`;
  tooltip.style.top = `${rect.bottom + 10}px`;
  
  // Mostrar con animación
  tooltip.style.opacity = '0';
  tooltip.style.transform = 'translateY(-10px)';
  tooltip.style.transition = 'all 0.3s ease';
  
  // Forzar reflow para que la transición funcione
  tooltip.offsetHeight;
  
  tooltip.style.opacity = '1';
  tooltip.style.transform = 'translateY(0)';
}

Variables CSS (propiedades personalizadas)

Las variables CSS combinadas con JavaScript permiten crear temas dinámicos y sistemas de diseño flexibles:

// Cambiar tema de color usando variables CSS
function setThemeColor(primaryColor, secondaryColor) {
  document.documentElement.style.setProperty('--primary-color', primaryColor);
  document.documentElement.style.setProperty('--secondary-color', secondaryColor);
  
  // Guardar preferencias
  localStorage.setItem('theme', JSON.stringify({
    primary: primaryColor,
    secondary: secondaryColor
  }));
}

// Ejemplo de uso
document.querySelector('#theme-selector').addEventListener('change', (e) => {
  const theme = e.target.value;
  
  if (theme === 'blue') {
    setThemeColor('#3498db', '#2980b9');
  } else if (theme === 'green') {
    setThemeColor('#2ecc71', '#27ae60');
  }
});

Optimización del rendimiento

Al manipular estilos, es importante considerar el rendimiento:

  • Minimiza los reflows: Agrupa los cambios de estilo para reducir recálculos de layout
// Mal (causa múltiples reflows)
element.style.width = '100px';
element.style.height = '100px';
element.style.margin = '10px';

// Mejor (un solo reflow)
element.style.cssText = 'width: 100px; height: 100px; margin: 10px;';

// O usando clases (aún mejor)
element.classList.add('box-dimensions');
  • Usa requestAnimationFrame para animaciones suaves:
function animateProgress(element, targetWidth) {
  let width = 0;
  
  function step() {
    width += 2;
    element.style.width = `${width}%`;
    
    if (width < targetWidth) {
      requestAnimationFrame(step);
    }
  }
  
  requestAnimationFrame(step);
}

// Uso
animateProgress(document.querySelector('.progress-bar'), 75);

Ejemplo práctico: Sistema de notificaciones

Combinando clases y estilos para crear un sistema de notificaciones dinámico:

function showNotification(message, type = 'info') {
  const notification = document.createElement('div');
  notification.className = 'notification';
  notification.classList.add(`notification-${type}`);
  notification.textContent = message;
  
  // Añadir al DOM
  document.body.appendChild(notification);
  
  // Forzar reflow antes de añadir clase para activar transición
  notification.offsetHeight;
  
  // Mostrar con animación
  notification.classList.add('notification-visible');
  
  // Configurar auto-cierre
  setTimeout(() => {
    notification.classList.remove('notification-visible');
    
    // Eliminar del DOM después de la transición
    notification.addEventListener('transitionend', () => {
      notification.remove();
    });
  }, 5000);
  
  return notification;
}

Esta combinación de manipulación de clases y estilos permite crear interfaces dinámicas y responsivas que mejoran significativamente la experiencia del usuario, manteniendo un código limpio y fácil de mantener.

Aprendizajes de esta lección de JavaScript

  • Dominar el uso de innerText para manipular texto visible.
  • Comprender textContent para manejar texto oculto en el DOM.
  • Explorar nodeValue para interacciones precisas a nivel de nodo de texto.
  • Comparar las diferencias entre innerText, textContent y nodeValue.
  • Seleccionar la propiedad adecuada según las necesidades de estilo y rendimiento.
  • Aplicar estrategias de seguridad para evitar ataques XSS en manipulación de contenido.

Completa este curso de JavaScript y certifícate

Únete a nuestra plataforma de cursos de programación y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración