Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Layout Patterns and CSS Guide

Because Dioxamine renders plugins within an Android WebView inside Jetpack Compose, understanding how CSS containing blocks resolve height is essential for creating responsive interfaces.

Pattern A: Full-Screen App and Terminal Layout

Use this pattern for interactive terminals, real-time log viewers, code editors, or canvas games where the page should occupy the entire screen, lock document scrolling, and manage an internal scrolling panel.

/* Lock root document to exact physical viewport boundaries */
html, body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: var(--dioxamine-bg, #121212);
    color: var(--dioxamine-fg, #ffffff);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* Root application flex container */
#app {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

/* Fixed toolbar or header */
header {
    flex-shrink: 0;
    padding: 10px 14px;
    background-color: var(--dioxamine-card-bg, #1e1e1e);
    border-bottom: 1px solid var(--dioxamine-outline-variant, #333333);
}

/* Main scrollable viewport (terminal / log container) */
.scroll-content {
    flex: 1 1 0;
    min-height: 0; /* CRITICAL: Allows flex child to shrink below intrinsic content size */
    overflow-y: auto;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding: 12px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="app">
        <header>
            <h1>Terminal Console</h1>
        </header>
        <div id="terminal-container" class="scroll-content"></div>
    </div>
</body>
</html>

Pattern B: Standard Document and Page Layout

Use this pattern for information dashboards, settings pages, documentation readers, or card-based views that scroll naturally.

body {
    margin: 0;
    padding: 16px;
    background-color: var(--dioxamine-bg, #121212);
    color: var(--dioxamine-fg, #ffffff);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    -webkit-text-size-adjust: 100%;
}

.container {
    max-width: 720px;
    margin: 0 auto;
}

.card {
    background-color: var(--dioxamine-card-bg, #1e1e1e);
    color: var(--dioxamine-card-fg, #ffffff);
    border: 1px solid var(--dioxamine-outline-variant, #333333);
    border-radius: 12px;
    padding: 16px;
    margin-bottom: 16px;
}

High-Frequency DOM Updates Best Practice

When processing high-frequency streams (such as logcat or serial metrics emitting hundreds of lines per second), appending single DOM elements synchronously blocks the UI thread.

Always batch DOM insertions using DocumentFragment and a throttled render loop:

let pendingBatch = [];
let renderTimer = null;
const MAX_LINES = 1000;

function queueLine(text) {
    pendingBatch.push(text);
    if (!renderTimer) {
        renderTimer = setTimeout(flushBatch, 40); // 25fps batch flush
    }
}

function flushBatch() {
    renderTimer = null;
    if (pendingBatch.length === 0) return;

    const container = document.getElementById('log-container');
    const fragment = document.createDocumentFragment();
    const batch = pendingBatch.splice(0, pendingBatch.length);

    for (let i = 0; i < batch.length; i++) {
        const line = document.createElement('div');
        line.className = 'log-line';
        line.textContent = batch[i];
        fragment.appendChild(line);
    }

    container.appendChild(fragment);

    // Prune excess lines to prevent memory bloat
    while (container.childNodes.length > MAX_LINES) {
        container.removeChild(container.firstChild);
    }

    // Smooth auto-scroll
    container.scrollTop = container.scrollHeight;
}