← Назад к вопросам

Как браузер узнает размер изображения?

1.0 Junior🔥 141 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как браузер узнает размер изображения

Это хороший вопрос для backend-разработчика, так как понимание этого процесса критично для оптимизации и работы с HTTP заголовками, CDN, и кэшированием.

Способ 1: Явное указание размера в HTML/CSS

Первый и самый прямой способ — явно указать размеры в коде:

<!-- HTML атрибуты -->
<img src="image.jpg" width="800" height="600" alt="Product" />

<!-- CSS стили -->
<img src="image.jpg" style="width: 800px; height: 600px;" alt="Product" />

<!-- CSS правило -->
<style>
  img {
    width: 800px;
    height: 600px;
  }
</style>
<img src="image.jpg" alt="Product" />

Этот способ не требует загрузки файла — браузер сразу знает размеры.

Способ 2: Чтение данных изображения (Image Header)

Когда браузер начинает загружать изображение, первые байты файла содержат информацию о размере. Для разных форматов это расположено по-разному:

PNG: размер в первых 24 байтах

Первые 8 байт: PNG signature (89 50 4E 47 0D 0A 1A 0A)
Следующие 4 байта: IHDR chunk
Далее 4 байта: width (big-endian)
Далее 4 байта: height (big-endian)

JPEG: информация в маркерах (SOF)

JPEG начинается с FFD8 (SOI маркер)
Размер находится в SOF маркере обычно в начале файла

GIF: размер в первых 10 байтах

Первые 3 байта: 'GIF' (47 49 46)
Далее 3 байта: версия ('89a' или '87a')
Далее 2 байта: width (little-endian)
Далее 2 байта: height (little-endian)

WebP: информация в заголовке RIFF

Первые 4 байта: 'RIFF'
Далее 4 байта: размер файла
Далее 4 байта: 'WEBP'
Далее 4 байта: 'VP8 '
Далее информация о размере

Когда браузер получает размер

До полной загрузки изображения

// JavaScript может получить размер, слушая события
const img = new Image();
img.src = 'large-image.jpg';

img.addEventListener('load', () => {
  console.log('Width:', img.width);   // Размер из заголовка
  console.log('Height:', img.height); // Размер из заголовка
  // В этот момент изображение полностью загружено
});

Однако браузер МОЖЕТ узнать размер раньше, если:

  1. Размеры явно указаны в HTML/CSS
  2. Браузер прочитал заголовок файла (первые байты)

Практика: что отправляет backend

Для backend-разработчика это означает, что можно отправить информацию о размере в ответе API:

// Express endpoint для получения информации об изображении
app.get('/api/images/:id', async (req, res) => {
  const image = await Image.findById(req.params.id);
  
  res.json({
    id: image.id,
    url: image.url,
    width: image.width,     // Размер из БД
    height: image.height,   // Размер из БД
    format: image.format,   // PNG, JPEG, WebP
    size: image.fileSize,   // Размер файла
    mimeType: 'image/jpeg'
  });
});

HTTP заголовки и размер

При загрузке изображения браузер получает HTTP заголовки, которые могут влиять на отображение:

HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 245678          // Размер файла (не размер изображения!)
Cache-Control: public, max-age=31536000
Content-Encoding: gzip          // Может быть сжато
X-Image-Width: 800              // Кастомный заголовок (если нужен)
X-Image-Height: 600

У браузера есть Content-Length, но это размер ФАЙЛА, не разрешение изображения.

Процесс загрузки изображения

1. Браузер встречает <img src="image.jpg">
   ↓
2. Отправляет HTTP GET запрос
   ↓
3. Backend отправляет ответ с заголовками:
   - Content-Type: image/jpeg
   - Content-Length: 245678
   ↓
4. Браузер начинает получать bytes
   ↓
5. Первые байты содержат информацию о размере (заголовок формата)
   ↓
6. Браузер МОЖЕТ узнать размер на этом этапе (даже не дождавшись конца)
   ↓
7. Браузер рисует картину в зарезервированном месте
   ↓
8. По мере загрузки браузер заполняет image
   ↓
9. Load event когда все байты получены

Оптимизация: Priority Hints

Browser может использовать размер для приоритизации загрузок:

<!-- Высокий приоритет (LCP) -->
<img
  src="hero.jpg"
  width="1200"
  height="600"
  fetchpriority="high"
  loading="eager"
  alt="Hero image"
/>

<!-- Низкий приоритет (below the fold) -->
<img
  src="footer.jpg"
  width="800"
  height="300"
  loading="lazy"
  alt="Footer image"
/>

Зная размеры, браузер может:

  • Рассчитать макет до загрузки
  • Приоритизировать важные изображения
  • Отложить загрузку non-critical изображений

Чтение размера в Node.js backend

Если backend обрабатывает загруженные изображения:

const sharp = require('sharp');
const fs = require('fs');

async function getImageDimensions(filePath) {
  try {
    const metadata = await sharp(filePath).metadata();
    
    return {
      width: metadata.width,
      height: metadata.height,
      format: metadata.format,        // jpeg, png, webp, gif
      colorspace: metadata.space,     // srgb, rgb, etc
      hasAlpha: metadata.hasAlpha,    // true if transparency
      density: metadata.density,      // DPI
      chromaSubsampling: metadata.chromaSubsampling
    };
  } catch (error) {
    throw new Error('Failed to read image metadata: ' + error.message);
  }
}

// Использование при загрузке
app.post('/api/images/upload', upload.single('image'), async (req, res) => {
  try {
    const dimensions = await getImageDimensions(req.file.path);
    
    const image = await Image.create({
      url: req.file.filename,
      width: dimensions.width,
      height: dimensions.height,
      format: dimensions.format,
      fileSize: req.file.size
    });
    
    res.json(image);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

Lazy Loading и размеры

Для lazy-loaded изображений размеры особенно важны:

<!-- Без размеров: layout shift когда изображение загружается -->
<img
  src="image.jpg"
  loading="lazy"
  alt="Image"
/>

<!-- С размерами: браузер зарезервирует место, layout shift избегнут -->
<img
  src="image.jpg"
  width="400"
  height="300"
  loading="lazy"
  alt="Image"
/>

<!-- Еще лучше: aspect-ratio -->
<img
  src="image.jpg"
  width="400"
  height="300"
  style="aspect-ratio: 4/3; width: 100%; height: auto;"
  loading="lazy"
  alt="Image"
/>

NextJS Image Component

В Next.js размеры критичны:

import Image from 'next/image';

export default function Product({ product }) {
  return (
    <Image
      src={product.imageUrl}
      width={800}           // Обязательно для static/dynamic
      height={600}
      alt={product.name}
      priority={true}       // LCP optimization
      quality={85}          // Сжатие JPEG
    />
  );
}

Заключение

Браузер узнает размер изображения несколькими путями:

  1. Из HTML/CSS атрибутов — сразу, без загрузки файла
  2. Из заголовка файла — в первых байтах (PNG, JPEG, GIF, WebP)
  3. После полной загрузки — из метаданных изображения

Для backend-разработчика это значит:

  • Всегда указывать размеры в API ответах
  • Сохранять размеры при загрузке изображений
  • Отправлять правильные Content-Type заголовки
  • Помнить о Core Web Vitals при работе с изображениями