You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elm开发:页面加载及resize时获取窗口宽度以适配图片

Hey there! Let's break down your Elm landing page challenges into two solvable parts—grabbing the initial window width on page load, and swapping out images in a cleaner way than using background-image.

1. Getting the Initial Window Width

You already have resize handling set up, but to get the width on page load, you can use Browser.Dom.getViewport to fetch the initial viewport dimensions. Here's how to wire this into your Elm architecture:

First, update your Msg type to handle the initial viewport data:

type Msg
    = GotInitialViewport Browser.Dom.Viewport
    | WindowResized Int Int

Then, in your init function, send a command to fetch the viewport immediately:

import Browser.Dom
import Task

init : () -> ( Model, Cmd Msg )
init _ =
    ( { windowWidth = 0 -- Temporary placeholder; will be updated shortly
      , -- Your other model fields here
      }
    , Browser.Dom.getViewport |> Task.perform GotInitialViewport
    )

Next, handle the viewport response in your update function, and reuse the same logic for resize events to keep things DRY:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotInitialViewport viewport ->
            ( { model | windowWidth = round viewport.viewport.width }
            , Cmd.none
            )

        WindowResized width _ ->
            ( { model | windowWidth = width }
            , Cmd.none
            )

Your existing resize subscription stays mostly the same—just map to the new WindowResized msg:

import Window

subscriptions : Model -> Sub Msg
subscriptions _ =
    Window.resizes (\{ width, height } -> WindowResized width height)

This way, your model will have the correct window width right after the page loads, not just when the window is resized.

2. Better Image Switching (Ditch background-image)

Using background-image for content images is far from ideal—they're not semantic, hard to make accessible, and miss out on native image features like lazy loading. Instead, use a standard <img> tag and dynamically set its src based on your window width state.

Here's how to implement this in your view:

view : Model -> Html Msg
view model =
    let
        -- Define your breakpoints and image paths clearly
        mobileBreakpoint = 768
        heroImageSrc =
            if model.windowWidth < mobileBreakpoint then
                "/images/hero-mobile.jpg"
            else
                "/images/hero-desktop.jpg"
    in
    div [ class "hero-container" ]
        [ img
            [ src heroImageSrc
            , alt "Hero banner: Your landing page headline here" -- Critical for accessibility
            , class "hero-image"
            , loading "lazy" -- Optional: Enable native lazy loading
            ]
            []
        -- Add your other landing page content here
        ]

Why this is better than background-image:

  • Semantics: Search engines and screen readers recognize <img> as content, whereas background images are treated as decorative.
  • Accessibility: You can easily add descriptive alt text, which is impossible with background images.
  • Control: Native image attributes like loading="lazy" or width/height help with performance and layout stability.
  • Maintainability: The image logic lives directly in your view, tied to your state, making it easier to debug and update than modifying CSS styles dynamically.

If you want to take it a step further, you can even handle image loading states (e.g., show a spinner while the image loads) by adding onLoad and onError handlers to the <img> tag and updating your model accordingly.


内容的提问来源于stack exchange,提问作者Mr Matten

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:11:04