> ## Documentation Index
> Fetch the complete documentation index at: https://resources.latex-cloud-studio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Advanced Table Features

> Master complex table layouts in LaTeX. Learn about long tables, landscape orientation, nested tables, and professional formatting techniques.

export const RenderedOutput = ({title = "Rendered output", ctaHref, ctaLabel = "Open LaTeX Cloud Studio", children}) => {
  const [isExpanded, setIsExpanded] = useState(false);
  const trackEditorCta = () => {
    const target = new URL(ctaHref, window.location.href);
    globalThis.posthog?.capture?.("docs_app_cta_clicked", {
      source_page: window.location.pathname,
      source_section: "rendered_output",
      cta_variant: "first_compiled_example",
      target_url: target.toString(),
      target_utm_source: target.searchParams.get("utm_source"),
      target_utm_medium: target.searchParams.get("utm_medium"),
      target_utm_campaign: target.searchParams.get("utm_campaign"),
      target_utm_content: target.searchParams.get("utm_content")
    }, {
      transport: "sendBeacon",
      send_instantly: true
    });
  };
  return <details className="rendered-output" onToggle={event => setIsExpanded(event.currentTarget.open)}>
      <summary className="rendered-output__summary">
        <span className="rendered-output__title">{title}</span>
        <span className="rendered-output__hint" aria-hidden="true">View compiled result</span>
      </summary>
      {isExpanded && <div className="rendered-output__content">
          {children}
          {ctaHref && <aside className="rendered-output__cta" aria-label="Continue in the LaTeX editor">
              <span>
                <strong>Ready to use this syntax?</strong>
                Continue in the browser editor when you want to adapt the example in a real project.
              </span>
              <a href={ctaHref} onClick={trackEditorCta}>{ctaLabel}<span aria-hidden="true"> →</span></a>
            </aside>}
        </div>}
    </details>;
};

export const LatexSource = ({filename, source}) => {
  const [copyStatus, setCopyStatus] = useState("Copy");
  const copySource = async () => {
    try {
      await navigator.clipboard.writeText(source);
      setCopyStatus("Copied");
    } catch {
      setCopyStatus("Select and copy");
    }
  };
  return <figure className="latex-source">
      <figcaption className="latex-source__header">
        <span className="latex-source__filename">{filename}</span>
        <button type="button" className="latex-source__copy" onClick={copySource} aria-live="polite">
          {copyStatus}
        </button>
      </figcaption>
      <pre className="latex-source__pre" aria-label={`LaTeX source: ${filename}`} tabIndex="0">
        <code className="language-latex">{source}</code>
      </pre>
    </figure>;
};

export const LatexPreview = ({src, alt, caption, width, height}) => {
  const minZoom = 1;
  const maxZoom = 3;
  const zoomStep = 0.5;
  const measureSvgContent = async (assetSrc, pageWidth, pageHeight) => {
    const cacheKey = "__latexCloudSvgContentBoxCache";
    const contentBoxCache = globalThis[cacheKey] ?? new Map();
    globalThis[cacheKey] = contentBoxCache;
    if (contentBoxCache.has(assetSrc)) return contentBoxCache.get(assetSrc);
    const measurement = (async () => {
      const assetUrl = new URL(assetSrc, window.location.href);
      if (assetUrl.origin !== window.location.origin) {
        throw new Error("Rendered output must use a same-origin SVG asset.");
      }
      const response = await fetch(assetUrl, {
        credentials: "same-origin"
      });
      if (!response.ok) throw new Error(`Rendered output request failed with ${response.status}.`);
      const source = await response.text();
      const documentNode = new DOMParser().parseFromString(source, "image/svg+xml");
      if (documentNode.querySelector("parsererror")) throw new Error("Rendered output is not valid SVG.");
      const sourceSvg = documentNode.documentElement;
      sourceSvg.querySelectorAll("script, foreignObject").forEach(node => node.remove());
      [sourceSvg, ...sourceSvg.querySelectorAll("*")].forEach(node => {
        [...node.attributes].forEach(attribute => {
          if ((/^on/i).test(attribute.name)) node.removeAttribute(attribute.name);
          if ((attribute.name === "href" || attribute.name === "xlink:href") && !attribute.value.startsWith("#")) {
            node.removeAttribute(attribute.name);
          }
        });
      });
      const measurementHost = document.createElement("div");
      measurementHost.className = "latex-preview__measurement-host";
      const measuredSvg = document.importNode(sourceSvg, true);
      measuredSvg.setAttribute("aria-hidden", "true");
      measurementHost.appendChild(measuredSvg);
      document.body.appendChild(measurementHost);
      try {
        const measuredElements = [...measuredSvg.children].filter(node => !["defs", "desc", "metadata", "style", "title"].includes(node.tagName.toLowerCase()));
        const elementBounds = measuredElements.map(node => node.getBBox()).filter(box => [box.x, box.y, box.width, box.height].every(Number.isFinite) && box.width > 0 && box.height > 0);
        if (elementBounds.length === 0) {
          throw new Error("Rendered output has no measurable visible content.");
        }
        const sortedBounds = [...elementBounds].sort((left, right) => left.y - right.y);
        const clusterGap = pageHeight * 0.045;
        const clusters = [];
        sortedBounds.forEach(box => {
          const current = clusters[clusters.length - 1];
          if (!current || box.y - current.bottom > clusterGap) {
            clusters.push({
              boxes: [box],
              bottom: box.y + box.height
            });
            return;
          }
          current.boxes.push(box);
          current.bottom = Math.max(current.bottom, box.y + box.height);
        });
        const contentClusters = clusters.filter(cluster => {
          const clusterBox = cluster.boxes.reduce((combined, box) => {
            const right = Math.max(combined.x + combined.width, box.x + box.width);
            const bottom = Math.max(combined.y + combined.height, box.y + box.height);
            const x = Math.min(combined.x, box.x);
            const y = Math.min(combined.y, box.y);
            return {
              x,
              y,
              width: right - x,
              height: bottom - y
            };
          });
          const centerY = clusterBox.y + clusterBox.height / 2;
          const isMarginFurniture = cluster.boxes.length <= 2 && clusterBox.width < pageWidth * 0.2 && clusterBox.height < pageHeight * 0.04 && (centerY < pageHeight * 0.08 || centerY > pageHeight * 0.8);
          return !isMarginFurniture;
        });
        const visibleBounds = (contentClusters.length > 0 ? contentClusters : clusters).flatMap(cluster => cluster.boxes);
        const bounds = visibleBounds.reduce((combined, box) => {
          const right = Math.max(combined.x + combined.width, box.x + box.width);
          const bottom = Math.max(combined.y + combined.height, box.y + box.height);
          const x = Math.min(combined.x, box.x);
          const y = Math.min(combined.y, box.y);
          return {
            x,
            y,
            width: right - x,
            height: bottom - y
          };
        });
        const clampValue = (value, minimum, maximum) => Math.min(maximum, Math.max(minimum, value));
        const padding = Math.max(8, Math.min(pageWidth, pageHeight) * 0.025);
        const x = clampValue(bounds.x - padding, 0, pageWidth);
        const y = clampValue(bounds.y - padding, 0, pageHeight);
        const right = clampValue(bounds.x + bounds.width + padding, 0, pageWidth);
        const bottom = clampValue(bounds.y + bounds.height + padding, 0, pageHeight);
        return {
          x,
          y,
          width: right - x,
          height: bottom - y
        };
      } finally {
        measurementHost.remove();
      }
    })();
    contentBoxCache.set(assetSrc, measurement);
    measurement.catch(() => contentBoxCache.delete(assetSrc));
    return measurement;
  };
  const renderPreviewAsset = ({contentBox: assetContentBox, loading}) => {
    if (!assetContentBox) {
      return <img className="latex-preview__asset" src={src} alt={alt} width={width} height={height} loading={loading} draggable="false" />;
    }
    return <svg className="latex-preview__asset" viewBox={`${assetContentBox.x} ${assetContentBox.y} ${assetContentBox.width} ${assetContentBox.height}`} preserveAspectRatio="xMidYMid meet" role="img" aria-label={alt}>
        <image href={src} x="0" y="0" width={width} height={height} />
      </svg>;
  };
  const [isOpen, setIsOpen] = useState(false);
  const [frameMode, setFrameMode] = useState("content");
  const [viewMode, setViewMode] = useState("fit");
  const [zoom, setZoom] = useState(minZoom);
  const [contentBox, setContentBox] = useState(null);
  const [measurementStatus, setMeasurementStatus] = useState("loading");
  const dialogRef = useRef(null);
  const closeButtonRef = useRef(null);
  const viewportRef = useRef(null);
  const previousFocusRef = useRef(null);
  const dragRef = useRef(null);
  useEffect(() => {
    let isCurrent = true;
    setMeasurementStatus("loading");
    measureSvgContent(src, width, height).then(box => {
      if (!isCurrent) return;
      setContentBox(box);
      setMeasurementStatus("ready");
    }).catch(() => {
      if (!isCurrent) return;
      setContentBox(null);
      setFrameMode("page");
      setMeasurementStatus("error");
    });
    return () => {
      isCurrent = false;
    };
  }, [height, src, width]);
  const closeViewer = useCallback(() => {
    setIsOpen(false);
  }, []);
  const openViewer = () => {
    previousFocusRef.current = document.activeElement;
    setFrameMode(contentBox ? "content" : "page");
    setViewMode("fit");
    setZoom(minZoom);
    setIsOpen(true);
  };
  const applyZoom = useCallback(nextZoom => {
    const boundedZoom = Math.min(maxZoom, Math.max(minZoom, nextZoom));
    setViewMode("custom");
    setZoom(boundedZoom);
  }, []);
  const zoomIn = useCallback(() => {
    applyZoom(viewMode === "fit" ? minZoom + zoomStep : zoom + zoomStep);
  }, [applyZoom, viewMode, zoom]);
  const zoomOut = useCallback(() => {
    applyZoom(viewMode === "fit" ? minZoom : zoom - zoomStep);
  }, [applyZoom, viewMode, zoom]);
  useEffect(() => {
    if (!isOpen) return undefined;
    const previousOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    closeButtonRef.current?.focus();
    return () => {
      document.body.style.overflow = previousOverflow;
      previousFocusRef.current?.focus?.();
    };
  }, [isOpen]);
  useEffect(() => {
    if (!isOpen) return undefined;
    const handleKeyDown = event => {
      if (event.key === "Escape") {
        event.preventDefault();
        closeViewer();
        return;
      }
      if ((event.key === "+" || event.key === "=") && !event.metaKey && !event.ctrlKey) {
        event.preventDefault();
        zoomIn();
        return;
      }
      if (event.key === "-" && !event.metaKey && !event.ctrlKey) {
        event.preventDefault();
        zoomOut();
        return;
      }
      if (event.key !== "Tab" || !dialogRef.current) return;
      const focusable = [...dialogRef.current.querySelectorAll('button:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])')];
      if (focusable.length === 0) return;
      const first = focusable[0];
      const last = focusable[focusable.length - 1];
      if (event.shiftKey && document.activeElement === first) {
        event.preventDefault();
        last.focus();
      } else if (!event.shiftKey && document.activeElement === last) {
        event.preventDefault();
        first.focus();
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [closeViewer, isOpen, zoomIn, zoomOut]);
  const startDrag = event => {
    if (event.button !== 0 || !viewportRef.current) return;
    const viewport = viewportRef.current;
    dragRef.current = {
      pointerId: event.pointerId,
      x: event.clientX,
      y: event.clientY,
      scrollLeft: viewport.scrollLeft,
      scrollTop: viewport.scrollTop
    };
    viewport.setPointerCapture(event.pointerId);
    viewport.dataset.dragging = "true";
  };
  const continueDrag = event => {
    const drag = dragRef.current;
    const viewport = viewportRef.current;
    if (!drag || !viewport || drag.pointerId !== event.pointerId) return;
    viewport.scrollLeft = drag.scrollLeft - (event.clientX - drag.x);
    viewport.scrollTop = drag.scrollTop - (event.clientY - drag.y);
  };
  const stopDrag = event => {
    const viewport = viewportRef.current;
    if (viewport?.hasPointerCapture(event.pointerId)) viewport.releasePointerCapture(event.pointerId);
    if (viewport) delete viewport.dataset.dragging;
    dragRef.current = null;
  };
  const activeContentBox = frameMode === "content" ? contentBox : null;
  const activeWidth = activeContentBox?.width ?? width;
  const activeHeight = activeContentBox?.height ?? height;
  const activeRatio = activeWidth / activeHeight;
  const inlineContentBox = measurementStatus === "ready" ? contentBox : null;
  const inlineWidth = inlineContentBox?.width ?? width;
  const inlineHeight = inlineContentBox?.height ?? height;
  const inlineGeometry = {
    aspectRatio: `${inlineWidth} / ${inlineHeight}`,
    maxWidth: `${30 * inlineWidth / inlineHeight}rem`
  };
  const imageStyle = viewMode === "fit" ? {
    aspectRatio: `${activeWidth} / ${activeHeight}`,
    width: "100%",
    maxWidth: `${Math.max(16, activeRatio * 78)}dvh`
  } : {
    aspectRatio: `${activeWidth} / ${activeHeight}`,
    width: `${zoom * 100}%`,
    maxWidth: "none"
  };
  const zoomLabel = viewMode === "fit" ? frameMode === "content" ? "Fit content" : "Full page" : `${Math.round(zoom * 100)}%`;
  return <figure className="latex-preview">
      <button type="button" className="latex-preview__trigger" onClick={openViewer} aria-haspopup="dialog" aria-label={`Open zoomable preview: ${alt}`}>
        <span className="latex-preview__page" style={inlineGeometry}>
          {measurementStatus === "loading" ? <span className="latex-preview__loading" role="status">Preparing compiled output…</span> : renderPreviewAsset({
    src,
    alt,
    width,
    height,
    contentBox: inlineContentBox,
    loading: "lazy"
  })}
        </span>
        <span className="latex-preview__trigger-label" aria-hidden="true">
          <span className="latex-preview__trigger-icon">⌕</span>
          Open viewer
        </span>
      </button>
      <figcaption className="latex-preview__caption">
        <span>
          {caption}
          {measurementStatus === "error" && <span className="latex-preview__status" role="status"> Content fit is unavailable; the complete vector page is shown.</span>}
        </span>
        <a href={src} target="_blank" rel="noreferrer" className="latex-preview__source-link">Open SVG</a>
      </figcaption>

      {isOpen && <div className="latex-preview__backdrop" onMouseDown={event => {
    if (event.target === event.currentTarget) closeViewer();
  }}>
          <section ref={dialogRef} className="latex-preview__dialog" role="dialog" aria-modal="true" aria-label={`Rendered LaTeX viewer: ${alt}`}>
            <header className="latex-preview__toolbar">
              <div className="latex-preview__identity">
                <span className="latex-preview__eyebrow">Compiled LaTeX</span>
                <span className="latex-preview__filename">{alt}</span>
              </div>
              <div className="latex-preview__controls" aria-label="Preview controls">
                <button type="button" className={frameMode === "content" && viewMode === "fit" ? "is-active" : undefined} disabled={!contentBox} onClick={() => {
    setFrameMode("content");
    setViewMode("fit");
    setZoom(minZoom);
  }}>
                  Fit content
                </button>
                <button type="button" className={frameMode === "page" && viewMode === "fit" ? "is-active" : undefined} onClick={() => {
    setFrameMode("page");
    setViewMode("fit");
    setZoom(minZoom);
  }}>
                  Full page
                </button>
                <span className="latex-preview__zoom-group">
                  <button type="button" onClick={zoomOut} disabled={viewMode === "fit" || zoom <= minZoom} aria-label="Zoom out">−</button>
                  <output aria-live="polite" aria-label="Current zoom">{zoomLabel}</output>
                  <button type="button" onClick={zoomIn} disabled={viewMode !== "fit" && zoom >= maxZoom} aria-label="Zoom in">+</button>
                </span>
                <a href={src} target="_blank" rel="noreferrer">Open SVG</a>
                <button ref={closeButtonRef} type="button" className="latex-preview__close" onClick={closeViewer} aria-label="Close rendered LaTeX viewer">
                  Close
                </button>
              </div>
            </header>
            <div ref={viewportRef} className="latex-preview__viewport" data-view-mode={viewMode} onPointerDown={startDrag} onPointerMove={continueDrag} onPointerUp={stopDrag} onPointerCancel={stopDrag}>
              <span className="latex-preview__dialog-page" style={imageStyle}>
                {renderPreviewAsset({
    src,
    alt,
    width,
    height,
    contentBox: activeContentBox
  })}
              </span>
            </div>
            <footer className="latex-preview__viewer-note">
              Compiler-generated vector output · Use +/− to zoom · Drag to pan · Esc to close
            </footer>
          </section>
        </div>}
    </figure>;
};

This guide covers advanced table features for complex documents, including multi-page tables, professional layouts, and specialized table environments.

<Info>
  **Prerequisites**: Familiarity with basic table creation. See [Creating Tables](/learn/latex/tables/creating-tables) if you need a refresher.
</Info>

## Long Tables

### Tables Spanning Multiple Pages

<LatexSource filename="longtable-basic.tex" source={"\\documentclass{article}\n\\usepackage{longtable}\n\\begin{document}\n\n\\begin{longtable}{lcc}\n\\caption{Long table example} \\label{tab:long} \\\\\n\\hline\n\\textbf{Name} & \\textbf{Value} & \\textbf{Unit} \\\\\n\\hline\n\\endfirsthead\n\n\\multicolumn{3}{c}{\\tablename\\ \\thetable\\ -- \\textit{Continued from previous page}} \\\\\n\\hline\n\\textbf{Name} & \\textbf{Value} & \\textbf{Unit} \\\\\n\\hline\n\\endhead\n\n\\hline\n\\multicolumn{3}{r}{\\textit{Continued on next page}} \\\\\n\\endfoot\n\n\\hline\n\\endlastfoot\n\n% Table data\nItem 1 & 10.5 & kg \\\\\nItem 2 & 23.1 & kg \\\\\nItem 3 & 45.7 & kg \\\\\n% ... many more rows ...\nItem 50 & 89.2 & kg \\\\\n\\end{longtable}\n\n\\end{document}"} />

<RenderedOutput title="Rendered output" ctaHref="https://app.latex-cloud-studio.com/?utm_source=resources&utm_medium=rendered_output&utm_campaign=docs_open_app&utm_content=learn_latex_tables_advanced_tables">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-01/page-1.svg" alt="Compiled PDF page 1 from longtable-basic.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment." width={595.276} height={841.89} />
</RenderedOutput>

### Longtable Features

<LatexSource filename="longtable-advanced.tex" source={"\\usepackage{longtable}\n\\usepackage{booktabs}\n\n\\begin{longtable}{@{}lrrr@{}}\n\\caption{Sales data over multiple pages} \\\\\n\\toprule\nProduct & Q1 & Q2 & Q3 \\\\\n\\midrule\n\\endfirsthead\n\n\\caption[]{(continued)} \\\\\n\\toprule\nProduct & Q1 & Q2 & Q3 \\\\\n\\midrule\n\\endhead\n\n\\midrule\n\\multicolumn{4}{r}{Continued on next page...} \\\\\n\\endfoot\n\n\\bottomrule\n\\multicolumn{4}{r}{Total: \\$1,234,567} \\\\\n\\endlastfoot\n\n% Data rows\nProduct A & 100 & 150 & 120 \\\\\nProduct B & 200 & 180 & 220 \\\\\n% ... more data ...\n\\end{longtable}\n\n% Column width control\n\\setlength{\\LTleft}{0pt}\n\\setlength{\\LTright}{0pt}\n\\begin{longtable}{|p{3cm}|p{5cm}|p{4cm}|}\n% Table content\n\\end{longtable}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-02/page-1.svg" alt="Compiled PDF page 1 from longtable-advanced.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment. The visible fragment is compiled inside the documented minimal article wrapper." width={595.276} height={841.89} />
</RenderedOutput>

## Landscape Tables

### Rotating Large Tables

<LatexSource filename="landscape-tables.tex" source={"\\documentclass{article}\n\\usepackage{rotating}\n\\usepackage{pdflscape}\n\\begin{document}\n\n% Sideways table\n\\begin{sidewaystable}\n  \\centering\n  \\caption{Wide table in landscape}\n  \\begin{tabular}{lccccccc}\n    \\hline\n    Category & Jan & Feb & Mar & Apr & May & Jun & Jul \\\\\n    \\hline\n    Sales & 100 & 120 & 135 & 110 & 145 & 160 & 155 \\\\\n    Costs & 80 & 85 & 90 & 88 & 95 & 100 & 98 \\\\\n    Profit & 20 & 35 & 45 & 22 & 50 & 60 & 57 \\\\\n    \\hline\n  \\end{tabular}\n\\end{sidewaystable}\n\n% Landscape page with table\n\\begin{landscape}\n\\begin{table}\n  \\centering\n  \\caption{Very wide table on landscape page}\n  \\begin{tabular}{l*{12}{c}}\n    % 12 columns of data\n  \\end{tabular}\n\\end{table}\n\\end{landscape}\n\n\\end{document}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-03/page-1.svg" alt="Compiled PDF page 1 from landscape-tables.tex" caption="Page 1 of 2. Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment." width={612} height={792} />

  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-03/page-2.svg" alt="Compiled PDF page 2 from landscape-tables.tex" caption="Page 2 of 2. Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment." width={792} height={612} />
</RenderedOutput>

### Rotating Table Content

<LatexSource filename="rotating-content.tex" source={"\\usepackage{rotating}\n\\usepackage{array}\n\n% Rotate column headers\n\\begin{tabular}{l*{5}{c}}\n\\hline\nCity &\n\\rotatebox{90}{Population} &\n\\rotatebox{90}{Area (km²)} &\n\\rotatebox{90}{Density} &\n\\rotatebox{90}{Founded} &\n\\rotatebox{90}{Elevation} \\\\\n\\hline\nNew York & 8.3M & 783 & 10,194 & 1624 & 10m \\\\\nLondon & 9.0M & 1,572 & 5,701 & 43 & 11m \\\\\nTokyo & 13.9M & 2,194 & 6,349 & 1457 & 40m \\\\\n\\hline\n\\end{tabular}\n\n% Angled headers\n\\newcolumntype{R}[1]{>{\\rotatebox{45}\\bgroup}l<{\\egroup}}\n\\begin{tabular}{l*{4}{R{1cm}}}\nProduct & Price & Stock & Sales & Revenue \\\\\n\\end{tabular}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-04/page-1.svg" alt="Compiled PDF page 1 from rotating-content.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment. The visible fragment is compiled inside the documented minimal article wrapper." width={612} height={792} />
</RenderedOutput>

## Nested and Complex Tables

### Tables Within Tables

<LatexSource filename="nested-tables.tex" source={"\\documentclass{article}\n\\usepackage{array}\n\\begin{document}\n\n\\begin{tabular}{|l|c|}\n\\hline\nCategory & Details \\\\\n\\hline\nGroup A &\n\\begin{tabular}{@{}lr@{}}\n  Item 1 & 10 \\\\\n  Item 2 & 20 \\\\\n  Item 3 & 30 \\\\\n  \\hline\n  Total & 60\n\\end{tabular} \\\\\n\\hline\nGroup B &\n\\begin{tabular}{@{}lr@{}}\n  Item X & 15 \\\\\n  Item Y & 25 \\\\\n  \\hline\n  Total & 40\n\\end{tabular} \\\\\n\\hline\n\\end{tabular}\n\n% More complex nesting\n\\begin{tabular}{|l|l|}\n\\hline\n\\multicolumn{2}{|c|}{Main Table} \\\\\n\\hline\nLeft cell with table &\n\\begin{tabular}[t]{@{}cc@{}}\n  \\multicolumn{2}{c}{Subtable} \\\\\n  A & B \\\\\n  C & D\n\\end{tabular} \\\\\n\\hline\n\\end{tabular}\n\n\\end{document}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-05/page-1.svg" alt="Compiled PDF page 1 from nested-tables.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment." width={595.276} height={841.89} />
</RenderedOutput>

### Mixed Content Tables

<LatexSource filename="mixed-content.tex" source={"\\usepackage{graphicx}\n\\usepackage{tikz}\n\n\\begin{tabular}{lcp{5cm}}\n\\hline\nType & Visual & Description \\\\\n\\hline\nCircle &\n\\begin{tikzpicture}[baseline=-0.5ex]\n  \\draw[fill=blue!20] (0,0) circle (0.5cm);\n\\end{tikzpicture} &\nA closed curve where all points are equidistant from the center. \\\\\n\\hline\nSquare &\n\\includegraphics[width=1cm]{square} &\nA quadrilateral with four equal sides and four right angles. \\\\\n\\hline\nFormula &\n$E = mc^2$ &\nEinstein's mass-energy equivalence equation. \\\\\n\\hline\n\\end{tabular}"} />

<RenderedOutput title="Expected effect">
  <Info>
    This excerpt depends on project files such as images, bibliography data, or included TeX sources that are not part of this standalone code box. Its exact output is project-specific, so no fabricated preview is shown.
  </Info>
</RenderedOutput>

## Professional Table Packages

### Using booktabs

<LatexSource filename="booktabs-professional.tex" source={"\\documentclass{article}\n\\usepackage{booktabs}\n\\usepackage{siunitx}\n\\begin{document}\n\n% Professional table design\n\\begin{table}\n  \\centering\n  \\caption{Experimental results with uncertainties}\n  \\begin{tabular}{l S[table-format=3.1] @{${}\\pm{}$} S[table-format=1.1] S[table-format=3.2]}\n    \\toprule\n    Sample & \\multicolumn{2}{c}{Mass (g)} & {Density (g/cm³)} \\\\\n    \\midrule\n    A & 123.4 & 0.5 & 2.34 \\\\\n    B & 87.2 & 0.3 & 1.98 \\\\\n    C & 156.9 & 0.8 & 3.12 \\\\\n    \\midrule\n    Mean & 122.5 & 0.5 & 2.48 \\\\\n    \\bottomrule\n  \\end{tabular}\n\\end{table}\n\n% Publication-quality table\n\\begin{table*} % Two-column span\n  \\centering\n  \\caption{Comparison of methods}\n  \\begin{tabular}{@{}lrrrrr@{}}\n    \\toprule\n    Method & \\multicolumn{2}{c}{Dataset A} & \\multicolumn{2}{c}{Dataset B} & Overall \\\\\n    \\cmidrule(lr){2-3} \\cmidrule(lr){4-5}\n    & Precision & Recall & Precision & Recall & F1-Score \\\\\n    \\midrule\n    Baseline & 0.82 & 0.79 & 0.75 & 0.81 & 0.79 \\\\\n    Proposed & \\textbf{0.91} & \\textbf{0.88} & \\textbf{0.87} & \\textbf{0.90} & \\textbf{0.89} \\\\\n    \\bottomrule\n  \\end{tabular}\n\\end{table*}\n\n\\end{document}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-07/page-1.svg" alt="Compiled PDF page 1 from booktabs-professional.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment." width={612} height={792} />
</RenderedOutput>

### Using threeparttable

<LatexSource filename="threeparttable.tex" source={"\\usepackage{threeparttable}\n\\usepackage{booktabs}\n\n\\begin{threeparttable}\n  \\caption{Results with footnotes}\n  \\begin{tabular}{lcc}\n    \\toprule\n    Treatment & Response\\tnote{a} & p-value \\\\\n    \\midrule\n    Control & 23.4 ± 2.1 & — \\\\\n    Drug A & 31.2 ± 1.8\\tnote{b} & 0.002 \\\\\n    Drug B & 28.9 ± 2.3 & 0.041 \\\\\n    Combined & 35.6 ± 1.5\\tnote{b,c} & <0.001 \\\\\n    \\bottomrule\n  \\end{tabular}\n  \\begin{tablenotes}\n    \\item[a] Mean ± standard error\n    \\item[b] Significantly different from control (p < 0.01)\n    \\item[c] Synergistic effect observed\n  \\end{tablenotes}\n\\end{threeparttable}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-08/page-1.svg" alt="Compiled PDF page 1 from threeparttable.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment. The visible fragment is compiled inside the documented minimal article wrapper." width={595.276} height={841.89} />
</RenderedOutput>

## Advanced Formatting

### Custom Column Types

<LatexSource filename="custom-columns.tex" source={"\\documentclass{article}\n\\usepackage{array}\n\\usepackage{ragged2e}\n\\begin{document}\n\n% Define custom column types\n\\newcolumntype{L}[1]{>{\\raggedright\\arraybackslash}p{#1}}\n\\newcolumntype{C}[1]{>{\\centering\\arraybackslash}p{#1}}\n\\newcolumntype{R}[1]{>{\\raggedleft\\arraybackslash}p{#1}}\n\\newcolumntype{N}{@{}l@{}}\n\n\\begin{tabular}{L{3cm} C{3cm} R{3cm}}\n\\hline\nLeft aligned text with wrapping &\nCentered text that wraps nicely &\nRight aligned text with automatic wrapping \\\\\n\\hline\n\\end{tabular}\n\n% Currency column\n\\newcolumntype{$}{>{\\global\\let\\currentrowstyle\\relax}}\n\\newcolumntype{^}{>{\\currentrowstyle}}\n\\begin{tabular}{l $r<{\\,€}}\nProduct & \\multicolumn{1}{c}{Price} \\\\\n\\hline\nLaptop & 1299.99 \\\\\nMouse & 29.95 \\\\\nTotal & \\bfseries 1329.94 \\\\\n\\end{tabular}\n\n\\end{document}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-09/page-1.svg" alt="Compiled PDF page 1 from custom-columns.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment." width={595.276} height={841.89} />
</RenderedOutput>

### Conditional Formatting

<LatexSource filename="conditional-formatting.tex" source={"\\usepackage{xcolor}\n\\usepackage{array}\n\\usepackage{collcell}\n\n% Highlight negative numbers\n\\newcommand{\\colorednumber}[1]{%\n  \\ifdim#1pt<0pt\\color{red}\\fi#1%\n}\n\\newcolumntype{Q}{>{\\collectcell\\colorednumber}r<{\\endcollectcell}}\n\n\\begin{tabular}{lQ}\n\\hline\nItem & Profit \\\\\n\\hline\nProduct A & 150.00 \\\\\nProduct B & -25.50 \\\\\nProduct C & 75.25 \\\\\nProduct D & -10.00 \\\\\n\\hline\n\\end{tabular}\n\n% Conditional row coloring\n\\newcommand{\\rowcolor}[1]{\\rowcolor{#1}}\n\\begin{tabular}{lc}\n\\hline\nStatus & Count \\\\\n\\hline\n\\rowcolor{green!20} Success & 45 \\\\\n\\rowcolor{red!20} Failed & 3 \\\\\n\\rowcolor{yellow!20} Pending & 12 \\\\\n\\hline\n\\end{tabular}"} />

<RenderedOutput title="Expected effect">
  <Info>
    This code is a contextual or intentionally partial LaTeX excerpt, not a self-contained compilable document. Its visible result depends on the surrounding document, so the documentation shows the expected role without inventing a standalone preview.
  </Info>
</RenderedOutput>

## Table Automation

### Generating Tables from Data

<LatexSource filename="table-automation.tex" source={"\\usepackage{pgfplotstable}\n\\usepackage{filecontents}\n\n% Create data file\n\\begin{filecontents*}{data.csv}\nName,Score,Grade\nAlice,95,A\nBob,87,B\nCarol,92,A\nDavid,78,C\n\\end{filecontents*}\n\n% Load and display CSV\n\\pgfplotstabletypeset[\n  col sep=comma,\n  string type,\n  columns={Name,Score,Grade},\n  every head row/.style={\n    before row=\\toprule,\n    after row=\\midrule\n  },\n  every last row/.style={\n    after row=\\bottomrule\n  }\n]{data.csv}\n\n% With formatting\n\\pgfplotstabletypeset[\n  col sep=comma,\n  string type,\n  columns={Name,Score,Grade},\n  columns/Score/.style={\n    column type={r},\n    postproc cell content/.style={\n      @cell content={##1\\%}\n    }\n  }\n]{data.csv}"} />

<RenderedOutput title="Expected effect">
  <Info>
    This code is a contextual or intentionally partial LaTeX excerpt, not a self-contained compilable document. Its visible result depends on the surrounding document, so the documentation shows the expected role without inventing a standalone preview.
  </Info>
</RenderedOutput>

### Dynamic Table Generation

<LatexSource filename="dynamic-tables.tex" source={"\\usepackage{forloop}\n\n% Generate multiplication table\n\\newcounter{row}\n\\newcounter{col}\n\\begin{tabular}{c|*{10}{c}}\n× & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\\\\n\\hline\n\\forloop{row}{1}{\\value{row} < 11}{%\n  \\therow &\n  \\forloop{col}{1}{\\value{col} < 11}{%\n    \\number\\numexpr\\value{row}*\\value{col}\\relax\n    \\ifnum\\value{col}<10 & \\fi\n  }\\\\\n}\n\\end{tabular}\n\n% Calendar table\n\\newcommand{\\calendar}[2]{%\n  % #1 = month, #2 = year\n  \\begin{tabular}{|*{7}{c|}}\n    \\hline\n    \\multicolumn{7}{|c|}{\\textbf{#1 #2}} \\\\\n    \\hline\n    S & M & T & W & T & F & S \\\\\n    \\hline\n    % Calendar logic here\n  \\end{tabular}\n}"} />

<RenderedOutput title="Expected effect">
  <Info>
    This code is a contextual or intentionally partial LaTeX excerpt, not a self-contained compilable document. Its visible result depends on the surrounding document, so the documentation shows the expected role without inventing a standalone preview.
  </Info>
</RenderedOutput>

## Table Positioning and Float Control

### Precise Table Placement

<LatexSource filename="table-placement.tex" source={"\\usepackage{float}\n\\usepackage{placeins}\n\n% Force table here\n\\begin{table}[H]\n  \\centering\n  \\caption{This table appears exactly here}\n  \\begin{tabular}{cc}\n    A & B \\\\\n  \\end{tabular}\n\\end{table}\n\n% Keep tables in section\n\\FloatBarrier % No tables past this point\n\n% Adjust float parameters\n\\renewcommand{\\topfraction}{0.9}\n\\renewcommand{\\bottomfraction}{0.8}\n\\setcounter{topnumber}{2}\n\\setcounter{bottomnumber}{2}"} />

<RenderedOutput title="Rendered output">
  <LatexPreview src="/images/rendered/learn-latex-tables-advanced-tables-13/page-1.svg" alt="Compiled PDF page 1 from table-placement.tex" caption="Generated from the shown source with pdfLaTeX in the pinned LaTeXCloud TeX Live 2026 environment. The visible fragment is compiled inside the documented minimal article wrapper." width={595.276} height={841.89} />
</RenderedOutput>

## Performance Optimization

### Large Table Optimization

<LatexSource filename="optimize-tables.tex" source={"% For very large tables\n\\usepackage{array}\n\\usepackage{longtable}\n\n% Disable array stretching for speed\n\\renewcommand{\\arraystretch}{1.0}\n\n% Use simpler column types\n\\begin{longtable}{lll} % Instead of complex types\n\n% Compile only table\n\\usepackage{standalone}\n\\documentclass[preview]{standalone}\n\\begin{document}\n\\begin{tabular}{...}\n% Table content\n\\end{tabular}\n\\end{document}\n\n% Then include in main document\n\\includegraphics{table-output.pdf}"} />

<RenderedOutput title="Expected effect">
  <Info>
    This excerpt depends on project files such as images, bibliography data, or included TeX sources that are not part of this standalone code box. Its exact output is project-specific, so no fabricated preview is shown.
  </Info>
</RenderedOutput>

## How to Shrink a Table to Fit the Page or Column

When a table is wider than the text block, LaTeX will not shrink it for you — it
runs into the margin and reports an `Overfull \hbox`.

Scaling the whole table, font included, is the quickest fix. `\resizebox` from
`graphicx` takes a target width: `\resizebox{\textwidth}{!}{...}` wraps the
`tabular` and scales it to the text width, with `!` preserving the aspect ratio. Use
`\columnwidth` instead in a two-column layout.

Be aware that this shrinks the font along with the table, so a heavily scaled table
becomes hard to read. Before scaling, consider whether reducing column padding with
`\setlength{\tabcolsep}{4pt}`, wrapping text with a `p{3cm}` column, or using a
smaller font size for the table would keep it legible.

For tables that are simply too wide to ever fit, rotating with `sidewaystable` from
`rotating`, or splitting across pages with `longtable`, is better than scaling.

## Best Practices

<Tip>
  **Advanced table guidelines:**

  1. **Long tables**: Use `longtable` for multi-page tables
  2. **Wide tables**: Consider landscape orientation or font size reduction
  3. **Complex layouts**: Break into smaller, simpler tables when possible
  4. **Performance**: For very large tables, consider external generation
  5. **Consistency**: Define custom column types for repeated formats
  6. **Documentation**: Comment complex table structures
  7. **Testing**: Check table appearance at different page positions
</Tip>

## Troubleshooting

<Warning>
  **Common advanced table issues:**

  1. **Memory errors**: Large tables may exceed TeX memory - split or optimize
  2. **Float placement**: Use `\FloatBarrier` to control table positions
  3. **Column alignment**: Check array package column definitions
  4. **Page breaks**: Ensure longtable headers/footers are defined correctly
  5. **Compilation time**: Complex tables slow compilation - use caching
</Warning>

## Quick Reference

### Package Summary

| Package          | Purpose                 |
| ---------------- | ----------------------- |
| `longtable`      | Multi-page tables       |
| `rotating`       | Rotate tables           |
| `booktabs`       | Professional formatting |
| `tabularx`       | Auto-width tables       |
| `threeparttable` | Tables with notes       |
| `array`          | Enhanced columns        |
| `multirow`       | Multi-row cells         |
| `colortbl`       | Colored tables          |

### Advanced Commands

<LatexSource filename="example.tex" source={"\\toprule              % Top rule (booktabs)\n\\midrule              % Middle rule (booktabs)\n\\bottomrule           % Bottom rule (booktabs)\n\\cmidrule(lr){i-j}   % Partial rule with trim\n\\addlinespace        % Extra vertical space\n\\arraybackslash      % Restore \\\\ in array cells"} />

<RenderedOutput title="Expected effect">
  <Info>
    This code is a contextual or intentionally partial LaTeX excerpt, not a self-contained compilable document. Its visible result depends on the surrounding document, so the documentation shows the expected role without inventing a standalone preview.
  </Info>
</RenderedOutput>

***

<Info>
  **Next**: Ready to create your first LaTeX document? Check out our [How-to Guides](/learn/latex/how-to/articles) for practical examples and complete document templates.
</Info>
