Advanced Styling Techniques for THTMLPopup Widgets

How to Create Responsive Overlays with THTMLPopup

Overview

  • THTMLPopup is a lightweight HTML-based popup control (commonly used with THtmlViewer/related Delphi components). Use it to show contextual overlays, tooltips, menus, or small dialogs that adapt to different window sizes and DPI.

Key principles

  • Flexible sizing: size to content but enforce min/max dimensions.
  • Adaptive positioning: keep the popup within screen/workarea bounds and reposition when the parent moves or window resizes.
  • Responsive content: use CSS (percent widths, flexbox) and relative units (em, rem) inside the popup HTML.
  • DPI-awareness: scale fonts and sizes based on current DPI (Delphi: Screen.PixelsPerInch or VCL scaling).

Implementation steps (Delphi / component-agnostic)

  1. Create the popup

    • Instantiate THTMLPopup (or equivalent) and set its parent/owner.
    • Load HTML content via the component’s HTML property or SetDocumentStream.
  2. Use responsive HTML/CSS

    • Wrap content in a responsive container:
      • width: 100%; max-width: 400px; box-sizing: border-box;
      • Use flexbox for layout and media queries for small screens.
    • Use relative units: font-size: 0.95rem; padding: 0.5rem.
  3. Size to content with limits

    • After loading content, measure rendered size (component provides content size or use viewer’s DocumentWidth/Height).
    • Apply:
      • width := Min(Max(contentWidth, minW), maxW)
      • height := Min(Max(contentHeight, minH), maxH)
    • Reflow if dimensions changed.
  4. Smart positioning

    • Preferred anchor: coordinates or control bounds.
    • Compute popupRect anchored below/above or to the side.
    • If popupRect extends beyond Monitor.WorkArea, flip anchor or shift to fit.
    • Keep a small margin from screen edges (e.g., 8–12 px).
  5. Handle window/monitor/DPI changes

    • Subscribe to parent form’s OnResize/OnMove and to WMDPICHANGED (or Delphi scale events).
    • On such events: recompute position and sizes; reload CSS scale if needed.
  6. Close behavior & input focus

    • Close on outside click: capture mouse or set popup to close on deactivation.
    • Keyboard: handle Esc to close; manage Tab/Shift-Tab focus if interactive.
    • If interactive content (links/forms), keep focus inside until explicit close.
  7. Animation and performance

    • Use CSS transitions for fade/slide; keep animations short (120–200 ms).
    • Avoid heavy scripts inside popup; lazy-load images if needed.

Example CSS snippet (use inside popup HTML)

Code

.container { box-sizing: border-box; width: 100%; max-width: 420px; padding: 0.6rem; font-size: 0.95rem; display: flex; flex-direction: column; gap: 0.4rem; } @media (max-width: 360px) { .container { padding: 0.4rem; font-size: 0.9rem; } }

Practical tips

  • Provide both max-width and max-height and enable internal scrolling when needed.
  • Cache popup content when reused to avoid reload delays.
  • Test across multiple DPI settings and secondary monitors.
  • For touch, increase tap targets and add a small delay before auto-closing to avoid accidental dismissals.

Troubleshooting

  • Popup flickers on parent resize: debounce reposition calls (50–120 ms).
  • Content clipped on high-DPI monitors: recalculate sizes after WM_DPICHANGED.
  • Outside-click not detected: ensure popup window style allows deactivation messages or implement a transparent click-catcher window.

If you want, I can generate a ready-to-use Delphi example (component creation, positioning routine, and event handlers).

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *