Lesson 27 of 45 · Web pages

Links, images and media

A page is more than text: it links to other pages, shows pictures, plays sound and video and draws shapes. This lesson covers the elements for all of that, and the attributes that make them fast, accessible and safe.

A link takes the reader somewhere. Its url is required and its content is the text the reader clicks. The address can point to another site, to a file next to your page, or to a place on the same page: a url that starts with # scrolls to the element whose id is the rest of it. Two more kinds are worth knowing. mailto: opens the mail program with a new message, and tel: offers to call the number on a phone.

web-media-links.salam
page:
    title = "Links"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.8 end
    paragraph:
        content = "Read the "
        link: url = "#rules" content = "house rules" end
        span: content = " first, then write to " end
        link: url = "mailto:club@example.com" content = "the club" end
        span: content = " or call " end
        link: url = "tel:+15550100" content = "555 0100" end
        span: content = "." end
    end
    paragraph:
        link: url = "https://example.com/guide" target = "new" rel = "noopener" content = "The full guide (new tab)" end
    end
    paragraph:
        link:
            url = "maps/garden.pdf"
            download = "garden-map.pdf"
            type = "application/pdf"
            hreflang = "en"
            content = "Download the garden map"
        end
    end
    heading: id = "rules" size = 2 content = "House rules" end
    paragraph: content = "Keep the gate closed. Water the beds in the morning." end
end

The attributes in the example each do one job. target says where the page opens: new is a new tab (the HTML word is _blank, and both work), same is the current tab, and parent and top matter only inside frames. rel describes the relationship to the target. With noopener the new tab cannot reach back to your page, which matters for a link to a site you do not control, and nofollow asks search engines not to count the link. download makes the browser save the file instead of showing it, and its value is the suggested file name. type is the kind of file you expect and hreflang the language of the target page. Both are hints. ping lists addresses that are told when someone follows the link, and referrer policy controls how much of your address the target site is given.

Write link text that makes sense on its own, such as "the house rules", and not "click here": screen readers can read out a list of all the links on a page. A link cannot contain another link or a button, and the compiler reports an error (E116) if you try. It also refuses addresses like javascript: that would run code (E018).

Images

image shows a picture. The url is required. The text description is the alt attribute, and content sets the same attribute, so you can write whichever reads better. The description is what a screen reader says and what the browser shows when the file cannot be loaded. Describe what the picture tells, not what it is: "A red kite over green hills", not "image". If the picture is only decoration, give it an empty description, alt = "", and screen readers will skip it. When you give neither, the compiler writes the empty one for you.

web-media-image.salam
page:
    title = "Images"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    paragraph: content = "A photo with a description:" end
    image:
        content = "A red kite flying over green hills"
        width = 160
        height = 100
        loading = lazy
        decoding = async
        url = "data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%20160%20100%27%20width=%27160%27%20height=%27100%27%3E%3Crect%20width=%27160%27%20height=%27100%27%20fill=%27%23bae6fd%27/%3E%3Cpath%20d=%27M0%20100%20Q50%2055%20100%2085%20T160%2075%20V100Z%27%20fill=%27%2316a34a%27/%3E%3Cpath%20d=%27M110%2012%20L130%2032%20L110%2052%20L90%2032Z%27%20fill=%27%23dc2626%27/%3E%3Cpath%20d=%27M110%2052%20Q100%2070%20112%2082%27%20stroke=%27%23475569%27%20fill=%27none%27/%3E%3Ctext%20x=%276%27%20y=%2714%27%20font-size=%2711%27%20font-family=%27sans-serif%27%20fill=%27%230c4a6e%27%3E%3C/text%3E%3C/svg%3E"
    end
    paragraph: content = "A decorative picture has an empty description:" end
    image: alt = "" width = 80 height = 50 url = "data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%20160%20100%27%20width=%27160%27%20height=%27100%27%3E%3Crect%20width=%27160%27%20height=%27100%27%20fill=%27%23bae6fd%27/%3E%3Cpath%20d=%27M0%20100%20Q50%2055%20100%2085%20T160%2075%20V100Z%27%20fill=%27%2316a34a%27/%3E%3Cpath%20d=%27M110%2012%20L130%2032%20L110%2052%20L90%2032Z%27%20fill=%27%23dc2626%27/%3E%3Cpath%20d=%27M110%2052%20Q100%2070%20112%2082%27%20stroke=%27%23475569%27%20fill=%27none%27/%3E%3Ctext%20x=%276%27%20y=%2714%27%20font-size=%2711%27%20font-family=%27sans-serif%27%20fill=%27%230c4a6e%27%3E%3C/text%3E%3C/svg%3E" end
    paragraph: content = "A picture that fails to load shows its description instead:" end
    image: content = "Photo of the garden gate" width = 200 height = 40 url = "missing/gate.jpg" end
end

Always set width and height to the real size of the file. The browser then reserves the space before the picture arrives, and the text below does not jump when it does. loading = lazy tells the browser to fetch the picture only when the reader scrolls near it, which saves data for pictures far down the page. Leave the first picture on the page at the default, eager. decoding chooses whether decoding may happen off to the side (async) and fetch priority lets you mark the most important picture as high.

The long text in url is a data address: the whole picture written as text, so the example needs no extra file. The compiler accepts data addresses for images, audio, video and fonts and refuses the rest. In your own pages you will usually write a file name or an address instead.

One picture, many sizes

A phone and a large monitor do not need the same file. srcset lists several versions of the picture, and the browser picks one. There are two ways to describe them. With density descriptors, as in the example, each file is marked 1x, 2x and so on, and the browser chooses by the pixel density of the screen. With width descriptors, photo-480.jpg 480w, photo-960.jpg 960w, each file is marked with its real width, and sizes tells the browser how wide the picture will be drawn, for example sizes = "(max-width: 600px) 100vw, 600px". The url stays as the fallback for browsers that do not know srcset.

web-media-srcset.salam
import dom

page:
    title = "Image sets"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" line height = 1.6 end
    image:
        id = "swatch"
        content = "A color swatch (the files do not exist here)"
        width = 160
        height = 100
        srcset = "swatch.png 1x, swatch-2x.png 2x"
        url = "swatch.png"
        error = (): dom.SetText(dom.ById("chosen"), "The browser chose: " + dom.GetStr(dom.ById("swatch"), "currentSrc")) end
    end
    paragraph: id = "chosen" content = "Waiting for the browser." end
end

The files in this example do not exist, so the browser draws nothing. It still decides which one it would load, and the function named after error = runs when the image cannot be loaded and reads that choice from the currentSrc property of the image. On a screen with twice the pixels you would read the second name.

When the versions are not the same picture, for example a wide crop for a desktop and a tall one for a phone, use picture. Inside it, each source has a media condition and a srcset, and the browser takes the first source whose condition is true. The last child is always a normal image: it is the fallback and it carries the description. A source can also have a type, such as image/webp, so that browsers that do not know the format skip it.

web-media-picture.salam
page:
    title = "Picture"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    picture:
        source: media = "(min-width: 500px)" srcset = "data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%20320%20120%27%20width=%27320%27%20height=%27120%27%3E%3Crect%20width=%27320%27%20height=%27120%27%20fill=%27%23bae6fd%27/%3E%3Ccircle%20cx=%27260%27%20cy=%2736%27%20r=%2720%27%20fill=%27%23facc15%27/%3E%3Cpath%20d=%27M0%20120%20Q90%2060%20170%20100%20T320%2085%20V120Z%27%20fill=%27%2316a34a%27/%3E%3Ctext%20x=%278%27%20y=%2716%27%20font-size=%2712%27%20font-family=%27sans-serif%27%20fill=%27%230c4a6e%27%3Ewide%3C/text%3E%3C/svg%3E" end
        image:
            content = "Green hills under a yellow sun"
            url = "data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%20120%20160%27%20width=%27120%27%20height=%27160%27%3E%3Crect%20width=%27120%27%20height=%27160%27%20fill=%27%23bae6fd%27/%3E%3Ccircle%20cx=%2790%27%20cy=%2730%27%20r=%2716%27%20fill=%27%23facc15%27/%3E%3Cpath%20d=%27M0%20160%20Q40%2090%2080%20140%20T120%20120%20V160Z%27%20fill=%27%2316a34a%27/%3E%3Ctext%20x=%278%27%20y=%2716%27%20font-size=%2712%27%20font-family=%27sans-serif%27%20fill=%27%230c4a6e%27%3Enarrow%3C/text%3E%3C/svg%3E"
        end
    end
    paragraph: content = "In a window narrower than 500 pixels you see the tall picture. In a wider window the browser swaps in the wide one." end
end

Clickable image maps

An image map makes parts of one picture into separate links. The image names the map with use map = "#shapes", and an image map with name = "shapes" holds one area per hotspot. An area has a shape: rect with the coordinates left,top,right,bottom, circle with center-x,center-y,radius, poly with the corners as x1,y1,x2,y2 and so on, or default for everything not covered. The coordinates are in pixels of the picture as it is drawn. An area is a link, so it also takes url, target, rel, download, ping and referrer policy, and it needs alt, the text for people who cannot click the picture.

web-media-map.salam
import dom

page:
    title = "Image map"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    image:
        content = "A red square next to a blue circle"
        use map = "#shapes"
        width = 200
        height = 100
        url = "data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%20200%20100%27%3E%3Crect%20x=%2710%27%20y=%2710%27%20width=%2780%27%20height=%2780%27%20fill=%27%23dc2626%27/%3E%3Ccircle%20cx=%27150%27%20cy=%2750%27%20r=%2740%27%20fill=%27%232563eb%27/%3E%3C/svg%3E"
    end
    image map: name = "shapes"
        area: shape = "rect" coords = "10,10,90,90" alt = "red square" url = "#" click = (): dom.SetText(dom.ById("said"), "You chose the square.") end end
        area: shape = "circle" coords = "150,50,40" alt = "blue circle" url = "#" click = (): dom.SetText(dom.ById("said"), "You chose the circle.") end end
    end
    paragraph: id = "said" content = "Click a shape." end
end

In the example each area also has a click handler that writes into the paragraph. The older ismap attribute is different: on an image inside a link it makes the browser send the clicked coordinates to the server, which then decides what to do.

Audio and video

audio and video play sound and moving pictures without any plug-in. Add controls or the reader gets no way to start them. Give the file with url or, better, with one or more source children, each with its type. The browser takes the first one it can play, so list the best format first. The content text is shown only by a browser that cannot play the element at all.

web-media-audio.salam
page:
    title = "Audio"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    paragraph: content = "A short beep. Press play:" end
    audio:
        controls = true
        preload = "auto"
        content = "Your browser cannot play audio."
        source: url = "data:audio/wav;base64,UklGRnwCAABXQVZFZm10IBAAAAABAAEAoA8AAKAPAAABAAgAZGF0YVgCAACAgYSGg3xzbnJ+jpqbjXdhWGF6ma+wmnVRQU1zocPHqXVDKzlpp9Xeunk7HCthpNfiv39AHShbntTjxIZFHyVVmNDjyIxKICNPks3kzZJPIyBKjMjj0JhVJR9FhsTj1J5bKB1AgL/i16RhKxw7ebrg2qpnLxw3c7Xf3LBtMhwybbDc37VzNxwvZ6ra4Lp5OxwrYaTX4r+AQB0oW57U48SGRR8lVZjQ48iMSiAjT5LN5M2STyMgSozI49CYVSUfRYbE49SeWygdQIC/4tekYSscO3m64NqqZy8cN3O139ywbTIcMm2w3N+1czccL2eq2uC6eTscK2Gk1+K/f0AdKFue1OPEhkUfJVWY0OPIjEogI0+SzeTNkk8jIEqMyOPQmFUlH0WGxOPUnlsoHUB/v+LXpGErHDt5uuDaqmcvHDdztd/csG0yHDJtsNzftXM3HC9nqtrgunk7HCthpNfiv39AHShbntTjxIZFHyVVmNDjyIxKICNPks3kzZJPIyBKjMjj0JhVJR9FhsTj1J5bKB1AgL/i16RhKxw7ebrg2qpnLxw3c7Xf3LBtMhwybbDc37VzNxwvZ6ra4Lp5OxwrYaTX4r9/QB0oW57U48SGRR8lVZjQ48iMSiAjT5LN5M2STyMgSozI49CYVSUfRYbE49SeWygdQIC/4NWjYjAjQXq01s+lajssQ3WrzMmlcUU1RnKiwsKkd08+S3CauLujfFhHUG+TrrOgf2BQVm+NpaqcgmhaXXCInKGYhG9jZXKFlJmShHVsbHWCjI+Mg3p1dXqAhYaFgX59fn8=" type = "audio/wav" end
        source: url = "beep.mp3" type = "audio/mpeg" end
    end
    paragraph: content = "The browser plays the first source it understands." end
end

preload says how much to fetch before the reader presses play: none, metadata (only the duration and size) or auto. loop starts again at the end, and muted starts silent. autoplay starts at once, but browsers usually refuse it for sound, so it works reliably only together with muted. A video also has width and height, a poster picture shown until it plays, and plays inline, which stops phones from forcing it to full screen.

web-media-video.salam
page:
    title = "Video"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    video:
        width = 288
        controls = true
        autoplay = true
        muted = true
        loop = true
        plays inline = true
        preload = "auto"
        poster = "data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%2096%2054%27%3E%3Crect%20width=%2796%27%20height=%2754%27%20fill=%27%23134e4a%27/%3E%3Cpath%20d=%27M40%2018%20L40%2036%20L56%2027Z%27%20fill=%27%23ccfbf1%27/%3E%3C/svg%3E"
        content = "Your browser cannot play video."
        source: url = "data:video/webm;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAKAEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHWTbuMU6uEElTDZ1OsggEjTbuMU6uEHFO7a1OsggJq7AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmsCrXsYMPQkBNgIxMYXZmNjIuMy4xMDBXQYxMYXZmNjIuMy4xMDBEiYhAp3AAAAAAABZUrmvIrgEAAAAAAAA/14EBc8WIcy20VtKTuA+cgQAitZyDdW5kiIEAhoVWX1ZQOIOBASPjg4QdzWUA4JCwgWC6gTaagQJVsIRVuYEBElTDZ/tzc59jwIBnyJlFo4dFTkNPREVSRIeMTGF2ZjYyLjMuMTAwc3PWY8CLY8WIcy20VtKTuA9nyKFFo4dFTkNPREVSRIeUTGF2YzYyLjExLjEwMCBsaWJ2cHhnyKFFo4hEVVJBVElPTkSHkzAwOjAwOjAzLjAwMDAwMDAwMAAfQ7Z1QMHngQCjxIEAAIDwAwCdASpgADYAAEcIhYWIhYSIAgICdaoD+AIGwSzT6hw4cOHDhw4ZAP78KdH/iGej1Ml3/6Jr+ia/omv/obgAo5aBAfQA0QEAARAQABgAGFgv9AAIhSgAo5aBA+gA0QEAARAQABgAGFgv9AAIhSgAo5aBBdwA0QEAARAQABgAGFgv9AAIhSgAo5aBB9AA0QEAARAQABgAGFgv9AAIhSgAo5aBCcQA0QEAARAQABgAGFgv9AAIhSgAHFO7a5G7j7OBALeK94EB8YIBo/CBAw==" type = "video/webm" end
        track: url = "captions/en.vtt" kind = "subtitles" srclang = "en" label = "English" default = true end
    end
end

The track element adds text to a video or an audio file from a WebVTT file. Its kind is subtitles (a translation), captions (speech and sounds, for the deaf), descriptions, chapters or metadata. srclang is the language of the text, label is the name in the menu, and default turns it on at the start. The file in the example does not exist. Real pages need captions for anything that is spoken.

Frames and embedded objects

iframe shows another page inside yours. The page can be an address in url or a short document written in srcdoc. Give it a title so screen readers can announce it, and a width and height. Use loading = lazy for frames far down the page.

web-media-iframe.salam
page:
    title = "Frames"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    paragraph: content = "A separate little page, locked in a sandbox with no scripts:" end
    iframe:
        title = "Greeting"
        width = 320
        height = 90
        sandbox = ""
        loading = lazy
        srcdoc = "<body style='font-family:sans-serif'><h3>Inside the frame</h3><p>This page cannot run scripts.</p></body>"
        border = "2px solid #0f766e"
    end
end

A frame can bring a stranger's code into your page, so lock it down with sandbox. An empty sandbox = "" removes every permission: no scripts, no forms, no popups. You then give back only what the frame needs, by listing words such as allow-scripts or allow-forms, separated by spaces. Never combine allow-scripts with allow-same-origin for a page you do not trust. allow is a separate list for browser features, such as "fullscreen; camera", and allow fullscreen permits the full screen button. name gives the frame a name for scripts, and referrer policy works as for links.

embed and object place an external resource, such as a PDF, into the page. Both take a url, a type and a size. embed has no content. object shows its content when the browser cannot display the file, which is the place for a download link, and its form and name attributes connect it to a form. For a PDF, a plain link is often the better choice.

Canvas, SVG and math

canvas is a blank rectangle you draw on with code. Set its size with the width and height attributes, which are the number of pixels of the drawing surface. A size set with CSS only stretches those pixels, and the drawing turns blurry. Drawing itself is done through the dom package. dom.GetContext(canvas, "2d") returns the drawing tool, dom.SetStr sets a property of it such as fillStyle, and dom.Call4 calls one of its methods with four numbers. The example stamps a square where you click: dom.GetNum(e, "offsetX") reads the click position inside the canvas from the event. The two functions above the page, stamp and wipe, are connected to the canvas and the button with click = stamp and click = wipe.

web-media-canvas.salam
import dom

func stamp(e: i64):
    ctx := dom.GetContext(dom.ById("pad"), "2d")
    dom.SetStr(ctx, "fillStyle", "#0f766e")
    _ := dom.Call4(ctx, "fillRect", dom.GetNum(e, "offsetX") - 10, dom.GetNum(e, "offsetY") - 10, 20, 20)
end

func wipe():
    ctx := dom.GetContext(dom.ById("pad"), "2d")
    _ := dom.Call4(ctx, "clearRect", 0, 0, 320, 160)
end

page:
    title = "Canvas"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    paragraph: content = "Click the canvas to stamp a square." end
    canvas: id = "pad" width = 320 height = 160 background = "#f1f5f9" border = "1px solid #94a3b8" click = stamp end
    box: margin top = 8
        button: content = "Clear" click = wipe end
    end
end

Text inside the canvas element, if you add some, is shown only when the browser cannot draw, and screen readers cannot see into the drawing. Put any information the drawing carries into the page as text as well.

svg draws with shapes that stay sharp at every size. The content of an svg is the markup of its shapes, written as it is, and it is not escaped, so use it only for markup you wrote yourself. view box is the coordinate system inside, four numbers min-x min-y width height, and width and height are the size on the page. The drawing scales to fit. xmlns is only needed when the SVG is a file of its own. math works the same way for mathematics, with MathML in its content: mi for a name, mo for an operator, mn for a number, mfrac for a fraction and msup for a power.

web-media-svg.salam
page:
    title = "SVG and math"
    global: selector = "body" font family = "system-ui, sans-serif" margin = "1.5rem" end
    svg:
        view box = "0 0 120 60"
        width = 240
        height = 120
        content = "<rect width='120' height='60' rx='8' fill='#ccfbf1'/><circle cx='30' cy='30' r='18' fill='#0f766e'/><text x='58' y='36' font-size='16' fill='#134e4a'>Salam</text>"
    end
    paragraph:
        content = "The area of a circle is "
        math: content = "<mi>A</mi><mo>=</mo><mi>&#960;</mi><msup><mi>r</mi><mn>2</mn></msup>" end
        span: content = "." end
    end
end

Reference: links, images and media

Every element of this lesson is below, with its attributes and a short example. The examples are checked by the compiler, so you can paste any of them inside a page: block. Files such as photo.jpg in the examples are only names, you need your own files to see them. The attributes that every element has, such as id and title, are in the lesson on the head and global attributes.

A link (HTML a). The required url is where it goes and the content is the text to click. It can hold text, an image or other inline content, but not another link or a button.

link: url = "/guide" content = "Read the guide" end

Required: url

AttributeWhat it doesExample

Images and maps

image (Persian: تصویر; HTML: <img>)

A picture (HTML img). The url is required. It has no children. Give it a description in alt or content, and its width and height.

image: url = "photo.jpg" content = "The garden gate in spring" width = 320 height = 200 end

Required: url · Void element, it cannot have children

AttributeWhat it doesExample
width
عرض
The width of the picture. A bare number means pixels. Set it, with height, to the real size of the file so the browser can reserve the space before the picture loads. [ulength]image: url = "photo.jpg" alt = "Gate" width = 240 height = 150 end
height
ارتفاع
The height of the picture, in pixels when it is a bare number. Together with width it lets the browser keep the picture's shape while it loads. [ulength]image: url = "photo.jpg" alt = "Gate" width = 240 height = 150 end
srcset
مجموعه منبع
A list of picture files for the browser to choose from, separated by commas. Each item is an address followed by 1x, 2x (screen density) or 480w, 960w (file width in pixels). [srcset]image: url = "photo-480.jpg" alt = "Gate" srcset = "photo-480.jpg 480w, photo-960.jpg 960w" sizes = "480px" end
sizes
اندازه‌ها
How wide the picture will be drawn, so the browser can pick from a srcset that uses w descriptors. A list of conditions with widths, ending with a default, for example (max-width: 600px) 100vw, 600px. [string]image: url = "photo-480.jpg" alt = "Gate" srcset = "photo-480.jpg 480w, photo-960.jpg 960w" sizes = "(max-width: 600px) 100vw, 600px" end
crossorigin
میان‌مبدا
Whether the request for a picture from another site carries credentials: anonymous (none) or use-credentials. It is needed when a script reads the pixels of a picture from another site. [enum: crossorigin]image: url = "https://cdn.example.com/map.png" alt = "Map" crossorigin = "anonymous" end
referrer policy
سیاست ارجاع
How much of this page's address is sent when the picture is requested. The words are the same as for a link: no-referrer, origin, same-origin and so on. [enum: referrer_policy]image: url = "https://img.example.com/a.png" alt = "Ad" referrer policy = "no-referrer" end
loading
بارگذاری
When to fetch the picture: eager at once (the default) or lazy only when the reader scrolls close to it. Use lazy for pictures below the first screen. [enum: loading]image: url = "footer-photo.jpg" alt = "The team" width = 320 height = 180 loading = "lazy" end
decoding
رمزگشایی
Whether the browser may decode the picture off to the side: async (yes, so the page is not held up), sync (decode together with the rest) or auto (the browser decides, the default). [enum: decoding]image: url = "big.jpg" alt = "A large panorama" width = 640 height = 200 decoding = "async" end
fetch priority
اولویت دریافت
A hint about how urgent the picture is: high, low or auto. Mark the main picture of the page high. [enum: fetch_priority]image: url = "hero.jpg" alt = "The harbour at dawn" width = 640 height = 260 fetch priority = "high" end
use map
نقشه
Connects the picture to an image map. The value is a # followed by the name of the map. [string]image: url = "plan.png" alt = "Floor plan" use map = "#rooms" end image map: name = "rooms" area: shape = "rect" coords = "0,0,50,50" alt = "Kitchen" url = "#kitchen" end end
ismap
نقشه سمت سرور
A boolean. On an image inside a link, it makes the browser add the click position to the address, so a server can decide what the click meant. Rarely needed today. [bool]link: url = "/where" image: url = "map.png" alt = "Map" ismap = true end end
url
نشانی
The address of the picture file, required. It can be a file name, a full address or a data address for small pictures. [url]image: url = "images/kite.png" alt = "A red kite" end
alt
جایگزین
The text description of the picture. Screen readers read it, and the browser shows it if the file cannot be loaded. Use an empty value (alt = "") for a picture that is only decoration. [string]image: url = "chart.png" alt = "Rainfall by month, highest in March" end
content
محتوا
Another way to write alt: the text you give as content becomes the description. Use whichever reads better; do not give both. [string]image: url = "logo.png" content = "Salam logo" end

picture (Persian: عکس; HTML: <picture>)

A container that lets the browser choose between several versions of a picture. It holds source elements and ends with the normal image, which is the fallback and carries the description.

picture:
    source: media = "(min-width: 700px)" srcset = "wide.jpg" end
    image: url = "narrow.jpg" alt = "The harbour" end
end

source (Persian: منبع; HTML: <source>)

One candidate file for a picture, an audio or a video. The browser uses the first one whose conditions it meets and whose type it understands. It has no content.

video: controls = true
    source: url = "intro.webm" type = "video/webm" end
    source: url = "intro.mp4" type = "video/mp4" end
end

Only inside: picture, video, audio · Void element, it cannot have children

AttributeWhat it doesExample
width
عرض
The width of the picture file of this candidate, in pixels. It helps the browser keep the right shape before the file arrives. [ulength]picture: source: srcset = "wide.jpg" media = "(min-width: 700px)" width = 1200 height = 600 end image: url = "narrow.jpg" alt = "The harbour" end end
height
ارتفاع
The height of the picture file of this candidate, in pixels. Give it together with width. [ulength]picture: source: srcset = "square.jpg" media = "(max-width: 400px)" width = 400 height = 400 end image: url = "wide.jpg" alt = "The harbour" end end
url
نشانی
The address of the audio or video file. Inside a picture use srcset instead. [url]audio: controls = true source: url = "song.mp3" type = "audio/mpeg" end end
srcset
مجموعه منبع
The picture files of this candidate inside a picture, written like the srcset of an image. [srcset]picture: source: srcset = "photo.avif 1x, photo-2x.avif 2x" type = "image/avif" end image: url = "photo.jpg" alt = "Gate" end end
sizes
اندازه‌ها
How wide the picture will be drawn, as for an image, used with w descriptors in srcset. [string]picture: source: srcset = "s-480.jpg 480w, s-960.jpg 960w" sizes = "(max-width: 600px) 100vw, 600px" end image: url = "s-480.jpg" alt = "Gate" end end
type
نوع
The file type of this candidate, as a MIME type such as image/webp or video/mp4. A browser that does not know it skips the candidate without fetching. [mime]picture: source: srcset = "photo.webp" type = "image/webp" end image: url = "photo.jpg" alt = "Gate" end end
media
رسانه
A media condition, written as in CSS. The candidate is used only while the condition is true, such as (min-width: 700px) or (orientation: portrait). [media_query]picture: source: media = "(orientation: portrait)" srcset = "tall.jpg" end image: url = "wide.jpg" alt = "The harbour" end end

image map (Persian: نقشه تصویر; HTML: <map>)

A set of clickable regions for an image (HTML map). The name is required and an image points at it with use map. Its children are area elements.

image map: name = "rooms"
    area: shape = "circle" coords = "40,40,30" alt = "Kitchen" url = "#kitchen" end
end

Required: name

AttributeWhat it doesExample
name
نام
The name of the map, required. An image refers to it as use map = "#name". [string]image map: name = "shapes" area: shape = "rect" coords = "0,0,40,40" alt = "Box" url = "#box" end end

area (Persian: ناحیه; HTML: <area>)

One clickable region of an image map. It is a link: it takes url, target and the other link attributes, and its shape and coords say where it is. It has no content.

image map: name = "m"
    area: shape = "rect" coords = "10,10,90,60" alt = "Home" url = "/" end
end

Void element, it cannot have children

AttributeWhat it doesExample
url
نشانی
Where a click on the region goes. Same kinds of address as for a link. [url]image map: name = "m" area: shape = "rect" coords = "0,0,50,50" alt = "Contact" url = "mailto:hi@example.com" end end
coords
مختصات
The points of the region as numbers separated by commas, in pixels of the picture. For rect: left,top,right,bottom. For circle: x,y,radius. For poly: x1,y1,x2,y2,.... [string]image map: name = "m" area: shape = "poly" coords = "10,60,50,10,90,60" alt = "Roof" url = "#roof" end end
shape
قالب ناحیه
The shape of the region: rect, circle, poly, or default for everything not covered by another area. [enum: area_shape]image map: name = "m" area: shape = "circle" coords = "50,50,30" alt = "Sun" url = "#sun" end end
target
هدف
Where the page opens, with the same words as for a link: new, same, parent, top. [enum: target]image map: name = "m" area: shape = "rect" coords = "0,0,50,50" alt = "Docs" url = "https://example.com" target = "new" end end
download
دانلود
Saves the target as a file instead of opening it, as for a link. The value is the suggested file name. [string]image map: name = "m" area: shape = "rect" coords = "0,0,50,50" alt = "Menu" url = "menu.pdf" download = "menu.pdf" end end
rel
رابطه
How the target relates to the page, with the same words as for a link, such as noopener or nofollow. [token (list)]image map: name = "m" area: shape = "rect" coords = "0,0,50,50" alt = "Partner" url = "https://example.org" target = "new" rel = "noopener" end end
referrer policy
سیاست ارجاع
How much of this page's address is sent to the target, as for a link. [enum: referrer_policy]image map: name = "m" area: shape = "rect" coords = "0,0,50,50" alt = "Away" url = "https://example.com" referrer policy = "no-referrer" end end
ping
پینگ
Addresses that are notified when the region is followed, as for a link. [url (list)]image map: name = "m" area: shape = "rect" coords = "0,0,50,50" alt = "Offer" url = "/offer" ping = "https://example.com/count" end end
alt
جایگزین
The text for the region, for people who cannot click on the picture. Screen readers read it as the name of the link. Always give it. [string]image map: name = "m" area: shape = "rect" coords = "0,0,50,50" alt = "Open the kitchen page" url = "/kitchen" end end

Audio and video

audio (Persian: صدا; HTML: <audio>)

A sound player. Add controls so the reader can start it. Give the file with url or with source children. The content is shown only by a browser that cannot play audio.

audio: controls = true url = "song.mp3" content = "Your browser cannot play audio." end
AttributeWhat it doesExample
url
نشانی
The address of the sound file. Use source children instead when you offer several formats. [url]audio: url = "rain.ogg" controls = true end
crossorigin
میان‌مبدا
Whether the request for a file from another site carries credentials: anonymous or use-credentials. Needed when a script analyses the sound. [enum: crossorigin]audio: url = "https://cdn.example.com/a.mp3" controls = true crossorigin = "anonymous" end
preload
پیش‌بارگذاری
How much to fetch before the reader presses play: none (nothing), metadata (only the length) or auto (as much as the browser likes). [enum: preload]audio: url = "long-talk.mp3" controls = true preload = "metadata" end
autoplay
پخش خودکار
A boolean. Start playing as soon as possible. Browsers ignore it for sound unless the element is also muted or the reader has already interacted with the page. [bool]audio: url = "ambient.mp3" autoplay = true muted = true loop = true end
loop
حلقه
A boolean. When the sound ends, start again from the beginning. [bool]audio: url = "rain.ogg" controls = true loop = true end
muted
بی‌صدا
A boolean. Start with the sound off. The reader can turn it on in the controls. [bool]audio: url = "rain.ogg" controls = true muted = true end
controls
کنترل‌ها
A boolean. With true the browser shows its own play, pause, volume and position controls. Without them the player is invisible. [bool]audio: url = "song.mp3" controls = true end

video (Persian: ویدیو; HTML: <video>)

A video player. Add controls so the reader can start it, and give width and height. The file comes from url or from source children, and subtitles from track children.

video: width = 320 controls = true poster = "cover.jpg"
    source: url = "clip.mp4" type = "video/mp4" end
end
AttributeWhat it doesExample
width
عرض
The width of the player in pixels. Set it, with height, to keep the page from jumping when the video loads. [ulength]video: url = "clip.mp4" controls = true width = 480 height = 270 end
height
ارتفاع
The height of the player in pixels. [ulength]video: url = "clip.mp4" controls = true width = 480 height = 270 end
url
نشانی
The address of the video file. Use source children instead when you offer several formats. [url]video: url = "clip.mp4" controls = true width = 320 end
crossorigin
میان‌مبدا
Whether the request for a file from another site carries credentials: anonymous or use-credentials. Needed when a script reads the frames, or when subtitles come from another site. [enum: crossorigin]video: url = "https://cdn.example.com/v.mp4" controls = true crossorigin = "anonymous" width = 320 end
preload
پیش‌بارگذاری
How much to fetch before the reader presses play: none, metadata or auto. metadata is a good choice for a page with many videos. [enum: preload]video: url = "clip.mp4" controls = true preload = "metadata" width = 320 end
autoplay
پخش خودکار
A boolean. Start at once. Browsers allow it only for a video that is also muted. [bool]video: url = "loop.mp4" autoplay = true muted = true loop = true plays inline = true width = 320 end
loop
حلقه
A boolean. When the video ends, start again from the beginning. [bool]video: url = "loop.mp4" controls = true loop = true width = 320 end
muted
بی‌صدا
A boolean. Start with the sound off. [bool]video: url = "clip.mp4" controls = true muted = true width = 320 end
controls
کنترل‌ها
A boolean. With true the browser shows its play, pause, volume, position and full screen controls. [bool]video: url = "clip.mp4" controls = true width = 320 end
poster
پوستر
A picture shown in place of the video until it plays. Give it a file name or address. [url]video: url = "clip.mp4" controls = true poster = "cover.jpg" width = 320 end
plays inline
پخش درجا
A boolean. On phones that would otherwise open every video in full screen, keep it playing inside the page. [bool]video: url = "clip.mp4" controls = true plays inline = true width = 320 end

track (Persian: شیار; HTML: <track>)

A text track for a video or audio: subtitles, captions, descriptions or chapters, from a WebVTT file. The url is required. It has no content.

video: url = "talk.mp4" controls = true width = 320
    track: url = "talk.en.vtt" kind = "subtitles" srclang = "en" label = "English" end
end

Required: url · Only inside: video, audio · Void element, it cannot have children

AttributeWhat it doesExample
url
نشانی
The address of the WebVTT file, required. [url]video: url = "talk.mp4" controls = true width = 320 track: url = "captions/talk.vtt" kind = "captions" srclang = "en" label = "Captions" end end
kind
نوع شیار
What the text is: subtitles (a translation of the speech), captions (speech and sounds, for deaf readers), descriptions (what is seen, for blind readers), chapters (titles for navigation) or metadata (for scripts, not shown). [enum: track_kind]video: url = "talk.mp4" controls = true width = 320 track: url = "talk.vtt" kind = "chapters" srclang = "en" label = "Chapters" end end
srclang
زبان شیار
The language of the text, as a language code such as en or fa. Required for subtitles. [lang]video: url = "talk.mp4" controls = true width = 320 track: url = "talk.fa.vtt" kind = "subtitles" srclang = "fa" label = "Persian" end end
label
برچسب
The name of the track in the player's menu, for example English. [string]video: url = "talk.mp4" controls = true width = 320 track: url = "talk.vtt" kind = "subtitles" srclang = "en" label = "English (UK)" end end
default
پیش‌فرض
A boolean. Turn this track on when the video starts, unless the reader has chosen another. Use it on one track only. [bool]video: url = "talk.mp4" controls = true width = 320 track: url = "talk.vtt" kind = "subtitles" srclang = "en" label = "English" default = true end end

Frames and embedded objects

iframe (Persian: قاب درونی; HTML: <iframe>)

A frame that shows another page inside this one. The page is an address in url or a short document in srcdoc. Give it a title and a size, and lock it down with sandbox.

iframe: url = "https://example.com/widget" title = "Widget" width = 400 height = 240 sandbox = "allow-scripts" end
AttributeWhat it doesExample
width
عرض
The width of the frame. A bare number means pixels. Browsers give a frame 300 pixels by default. [ulength]iframe: url = "https://example.com/embed" title = "Embedded" width = 480 height = 270 end
height
ارتفاع
The height of the frame. A bare number means pixels. The default is 150 pixels. [ulength]iframe: url = "https://example.com/embed" title = "Embedded" width = 480 height = 270 end
name
نام
A name for the frame, so that scripts can find it as a named window. The page language accepts only the four words (new, same, parent, top) as the target of a link. [string]iframe: name = "preview" title = "Preview" width = 300 height = 160 srcdoc = "<p>Empty</p>" end
referrer policy
سیاست ارجاع
How much of this page's address is sent when the frame's page is requested, with the same words as for a link. [enum: referrer_policy]iframe: url = "https://example.com/embed" title = "Embedded" width = 300 height = 160 referrer policy = "no-referrer" end
loading
بارگذاری
When to load the frame: eager at once or lazy when the reader scrolls close to it. Use lazy for a frame far down the page. [enum: loading]iframe: url = "https://example.com/map" title = "Map" width = 400 height = 240 loading = "lazy" end
srcdoc
محتوای سند
A complete small document, written as HTML text, to show in the frame instead of loading an address. It is escaped for you. [string]iframe: title = "Note" width = 300 height = 80 srcdoc = "<p style='font-family:sans-serif'>Hello from the frame</p>" end
allow fullscreen
اجازه تمام‌صفحه
A boolean. With true the page in the frame may go full screen. [bool]iframe: url = "https://example.com/player" title = "Player" width = 400 height = 240 allow fullscreen = true end
sandbox
قرنطینه
Restrictions for the frame. An empty value removes every permission. Words separated by spaces give some back: allow-scripts, allow-forms, allow-popups, allow-same-origin and others. Do not give allow-scripts and allow-same-origin together to a page you do not trust. [string]iframe: url = "https://example.com/form" title = "Form" width = 400 height = 240 sandbox = "allow-forms allow-scripts" end
allow
اجازه
A list of browser features the frame may use, separated by semicolons, such as fullscreen, camera, microphone or geolocation. The default is to allow none for pages from another site. [string]iframe: url = "https://example.com/call" title = "Video call" width = 400 height = 300 allow = "camera; microphone" end
url
نشانی
The address of the page to show in the frame. Use srcdoc instead for a short document written right here. [url]iframe: url = "https://example.com/embed" title = "Embedded page" width = 400 height = 200 end

embed (Persian: جاسازی; HTML: <embed>)

Places an external resource, such as a PDF, into the page (HTML embed). The url is required. It has no content, so there is no fallback text.

embed: url = "report.pdf" type = "application/pdf" width = 400 height = 300 end

Required: url · Void element, it cannot have children

AttributeWhat it doesExample
width
عرض
The width of the embedded area, in pixels when it is a bare number. [ulength]embed: url = "report.pdf" type = "application/pdf" width = 500 height = 300 end
height
ارتفاع
The height of the embedded area, in pixels when it is a bare number. [ulength]embed: url = "report.pdf" type = "application/pdf" width = 500 height = 300 end
url
نشانی
The address of the resource, required. [url]embed: url = "slides.pdf" type = "application/pdf" width = 400 height = 300 end
type
نوع
The MIME type of the resource, such as application/pdf. It helps the browser choose how to show it. [mime]embed: url = "report.pdf" type = "application/pdf" width = 400 height = 300 end

object (Persian: شیء; HTML: <object>)

An external resource shown in the page, with fallback content (HTML object). The url is required. If the browser cannot show the file, it shows the children instead, which is the place for a link to download it.

object: url = "report.pdf" type = "application/pdf" width = 400 height = 300
    link: url = "report.pdf" content = "Download the report" end
end

Required: url

AttributeWhat it doesExample
width
عرض
The width of the object, in pixels when it is a bare number. [ulength]object: url = "chart.svg" type = "image/svg+xml" width = 320 height = 200 content = "A chart" end
height
ارتفاع
The height of the object, in pixels when it is a bare number. [ulength]object: url = "chart.svg" type = "image/svg+xml" width = 320 height = 200 content = "A chart" end
type
نوع
The MIME type of the resource, such as application/pdf or image/svg+xml. [mime]object: url = "chart.svg" type = "image/svg+xml" width = 300 height = 200 content = "A chart" end
name
نام
A name for the object, for scripts and forms. [string]object: url = "chart.svg" type = "image/svg+xml" name = "chart" width = 300 height = 200 content = "A chart" end
url
نشانی
The address of the resource, required. It becomes the data attribute in HTML. [url]object: url = "chart.svg" type = "image/svg+xml" width = 300 height = 200 content = "A chart" end
form
فرم
The id of a form this object belongs to. The compiler checks that an element with that id exists on the page. [idref]box: id = "order" end object: form = "order" url = "widget.svg" type = "image/svg+xml" width = 200 height = 100 content = "Widget" end

Drawing

canvas (Persian: بوم; HTML: <canvas>)

A blank drawing surface (HTML canvas). You draw on it with code, through dom.GetContext. Give it an id so the code can find it, and set its size with the attributes, not with CSS.

canvas: id = "pad" width = 300 height = 150 background = "#f1f5f9" end
AttributeWhat it doesExample
width
عرض
The width of the drawing surface in pixels. This is the number of pixels you draw on. A width set with CSS only stretches them. [ulength]canvas: width = 400 height = 200 border = "1px solid #94a3b8" end
height
ارتفاع
The height of the drawing surface in pixels. The default is 150. [ulength]canvas: width = 400 height = 200 border = "1px solid #94a3b8" end

svg (Persian: اس‌وی‌جی; HTML: <svg>)

A vector picture written in place (HTML svg). Its content is the markup of the shapes, inserted as written and not escaped, so use only markup you wrote yourself. The picture stays sharp at every size.

svg: view box = "0 0 100 100" width = 120 height = 120 content = "<circle cx='50' cy='50' r='40' fill='tomato'/>" end
AttributeWhat it doesExample
view box
جعبه دید
The coordinate system inside the picture: four numbers, min-x min-y width height. The shapes are drawn in these units and scaled to the width and height on the page. [string]svg: view box = "0 0 200 100" width = 200 height = 100 content = "<rect width='200' height='100' fill='#ccfbf1'/>" end
width
عرض
The width of the picture on the page, such as 120 or 50%. [string]svg: view box = "0 0 100 100" width = "50%" height = 100 content = "<circle cx='50' cy='50' r='40' fill='gold'/>" end
height
ارتفاع
The height of the picture on the page, such as 120. [string]svg: view box = "0 0 100 100" width = 100 height = 100 content = "<circle cx='50' cy='50' r='40' fill='gold'/>" end
xmlns
فضای نام
The XML namespace address, http://www.w3.org/2000/svg. It is only needed when the SVG is saved as a file of its own. Inside a page you can leave it out. [absolute_url]svg: xmlns = "http://www.w3.org/2000/svg" view box = "0 0 100 100" width = 100 height = 100 content = "<circle cx='50' cy='50' r='40' fill='teal'/>" end

math (Persian: ریاضی; HTML: <math>)

A mathematical formula written in MathML (HTML math). Its content is the markup, inserted as written: mi for a name, mn for a number, mo for an operator, mfrac for a fraction, msup for a power, msqrt for a square root.

math: content = "<msqrt><mi>x</mi></msqrt><mo>=</mo><mfrac><mn>1</mn><mn>2</mn></mfrac>" end

Try it yourself

  • Write a page with a table of contents: a list of links that point with # to three headings further down. Add a link at the bottom that goes back to the top.
  • Draw your own picture in an svg: a house from a rect, a polygon for the roof and a circle for the sun. Then change the width and height but keep the view box, and watch it scale.
  • Change the image map so that the red square is a link to a heading on the same page, and add a third hotspot with poly.
  • Open the canvas example, make the stamp a different color on every click by using dom.Random(), and add a second button that fills the whole canvas.