Back

Back

Back

Mobile Rotation Alert

Mobile Rotation Alert

Page Contents

Page Contents

Page Contents

If your site works better in one orientation than another why not let your users know with this little component.
If your site works better in one orientation than another why not let your users know with this little component.
If your site works better in one orientation than another why not let your users know with this little component.

If your site works better in one orientation than another why not let your users know with this little component.

This little component came about when I was building a page that, no matter what I tried, just didn’t look great on mobile landscape.

I thought, why not let users know the site works better in portrait? So I built this component—and here it is.

It offers several customization options, like color, icon, placement, and whether it appears in landscape or portrait mode.

A handy component to have when you need it. And as always, you’re welcome!

If you are not sure how to add code to Framer watch this quick video.

Framer Code Component

Mobile Rotation Alert

1.0

1.0

1.0

1.0

// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Mobile Landscape Alert
// Version 1.0

import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"

function LandscapeToastWarning(props) {
    const {
        icon,
        iconSize,
        title,
        message,
        backgroundColor,
        textColor,
        previewMode,
        fontFamily,
        position,
        alertMode,
    } = props
    const [showToast, setShowToast] = useState(false)

    useEffect(() => {
        const checkOrientation = () => {
            const isMobile = window.innerWidth <= 768
            const isLandscape = window.innerWidth > window.innerHeight
            const shouldShow =
                previewMode ||
                (isMobile &&
                    ((alertMode === "Landscape" && isLandscape) ||
                        (alertMode === "Portrait" && !isLandscape)))
            setShowToast(shouldShow)
        }

        if (!previewMode) {
            checkOrientation()
            window.addEventListener("resize", checkOrientation)
            window.addEventListener("orientationchange", checkOrientation)

            return () => {
                window.removeEventListener("resize", checkOrientation)
                window.removeEventListener(
                    "orientationchange",
                    checkOrientation
                )
            }
        } else {
            setShowToast(true)
        }
    }, [previewMode, alertMode])

    if (!showToast) return null

    // Determine position styles based on the selected position prop
    const positionStyles = (() => {
        switch (position) {
            case "Top Left":
                return { top: "20px", left: "20px" }
            case "Top Center":
                return {
                    top: "20px",
                    left: "50%",
                    transform: "translateX(-50%)",
                }
            case "Top Right":
                return { top: "20px", right: "20px" }
            case "Bottom Left":
                return { bottom: "20px", left: "20px" }
            case "Bottom Center":
                return {
                    bottom: "20px",
                    left: "50%",
                    transform: "translateX(-50%)",
                }
            case "Bottom Right":
            default:
                return { bottom: "20px", right: "20px" }
        }
    })()

    return (
        <div
            style={{
                position: "fixed",
                backgroundColor: backgroundColor,
                color: textColor,
                padding: "20px 20px",
                borderRadius: "12px",
                display: "flex",
                alignItems: "center",
                boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
                width: "100%",
                maxWidth: "350px",
                zIndex: 1000,
                fontFamily: fontFamily,
                animation: "fadeInUp 0.5s ease-out",
                ...positionStyles,
            }}
        >
            {icon && (
                <span
                    style={{
                        marginRight: "20px",
                        display: "flex",
                        alignItems: "center",
                    }}
                >
                    <img
                        src={icon}
                        alt="icon"
                        style={{ width: iconSize, height: iconSize }}
                    />
                </span>
            )}
            <div style={{ flex: 1 }}>
                <h4
                    style={{
                        margin: 0,
                        fontSize: "16px",
                        fontWeight: "600",
                        color: textColor,
                        maxWidth: "90%",
                        paddingRight: "20px,",
                    }}
                >
                    {title}
                </h4>
                <p
                    style={{
                        margin: "4px 0 0",
                        fontSize: "14px",
                        color: textColor,
                        lineHeight: "1.4",
                        maxWidth: "90%",
                        paddingRight: "20px,",
                    }}
                >
                    {message}
                </p>
            </div>
            <button
                onClick={() => setShowToast(false)}
                style={{
                    position: "absolute",
                    top: "12px",
                    right: "12px",
                    width: "24px",
                    height: "24px",
                    background: "transparent",
                    border: "none",
                    color: textColor,
                    cursor: "pointer",
                    fontSize: "24px",
                    lineHeight: "24px",
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                }}
            >
                &times;
            </button>

            {/* Keyframe for fade-in and up animation */}
            <style>{`
                @keyframes fadeInUp {
                    from {
                        opacity: 0;
                        transform: translateY(20px);
                    }
                    to {
                        opacity: 1;
                        transform: translateY(0);
                    }
                }
            `}</style>
        </div>
    )
}

LandscapeToastWarning.defaultProps = {
    icon: "https://example.com/path-to-your-icon.png", // Replace with a valid icon URL
    iconSize: 24, // Default icon size
    title: "Better on portrait",
    message:
        "This site is optimized for portrait orientation on mobile devices. Please rotate your device for the best experience.",
    backgroundColor: "#34495e",
    textColor: "#ffffff",
    previewMode: true, // Enabled by default
    fontFamily: "Inter, sans-serif", // Default font family
    position: "Bottom Right", // Default position
    alertMode: "Landscape", // Default to landscape mode
}

addPropertyControls(LandscapeToastWarning, {
    icon: {
        type: ControlType.Image,
        title: "Icon",
    },
    iconSize: {
        type: ControlType.Number,
        title: "Icon Size",
        defaultValue: 24,
        min: 10,
        max: 50,
        unit: "px",
        displayStepper: true,
    },
    title: {
        type: ControlType.String,
        title: "Title",
    },
    message: {
        type: ControlType.String,
        title: "Message",
        displayTextArea: true,
    },
    backgroundColor: {
        type: ControlType.Color,
        title: "Background Color",
    },
    textColor: {
        type: ControlType.Color,
        title: "Text Color",
    },
    fontFamily: {
        type: ControlType.String,
        title: "Font Family",
        defaultValue: "Inter, sans-serif",
    },
    position: {
        type: ControlType.Enum,
        title: "Position",
        options: [
            "Top Left",
            "Top Center",
            "Top Right",
            "Bottom Left",
            "Bottom Center",
            "Bottom Right",
        ],
        optionTitles: [
            "Top Left",
            "Top Center",
            "Top Right",
            "Bottom Left",
            "Bottom Center",
            "Bottom Right",
        ],
        defaultValue: "Bottom Right",
    },
    alertMode: {
        type: ControlType.Enum,
        title: "Alert Mode",
        options: ["Landscape", "Portrait"],
        optionTitles: ["Landscape", "Portrait"],
        defaultValue: "Landscape",
    },
    previewMode: {
        type: ControlType.Boolean,
        title: "Preview Mode",
        defaultValue: true,
        enabledTitle: "On",
        disabledTitle: "Off",
    },
})

export default LandscapeToastWarning

CLICK TO COPY

// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Mobile Landscape Alert
// Version 1.0

import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"

function LandscapeToastWarning(props) {
    const {
        icon,
        iconSize,
        title,
        message,
        backgroundColor,
        textColor,
        previewMode,
        fontFamily,
        position,
        alertMode,
    } = props
    const [showToast, setShowToast] = useState(false)

    useEffect(() => {
        const checkOrientation = () => {
            const isMobile = window.innerWidth <= 768
            const isLandscape = window.innerWidth > window.innerHeight
            const shouldShow =
                previewMode ||
                (isMobile &&
                    ((alertMode === "Landscape" && isLandscape) ||
                        (alertMode === "Portrait" && !isLandscape)))
            setShowToast(shouldShow)
        }

        if (!previewMode) {
            checkOrientation()
            window.addEventListener("resize", checkOrientation)
            window.addEventListener("orientationchange", checkOrientation)

            return () => {
                window.removeEventListener("resize", checkOrientation)
                window.removeEventListener(
                    "orientationchange",
                    checkOrientation
                )
            }
        } else {
            setShowToast(true)
        }
    }, [previewMode, alertMode])

    if (!showToast) return null

    // Determine position styles based on the selected position prop
    const positionStyles = (() => {
        switch (position) {
            case "Top Left":
                return { top: "20px", left: "20px" }
            case "Top Center":
                return {
                    top: "20px",
                    left: "50%",
                    transform: "translateX(-50%)",
                }
            case "Top Right":
                return { top: "20px", right: "20px" }
            case "Bottom Left":
                return { bottom: "20px", left: "20px" }
            case "Bottom Center":
                return {
                    bottom: "20px",
                    left: "50%",
                    transform: "translateX(-50%)",
                }
            case "Bottom Right":
            default:
                return { bottom: "20px", right: "20px" }
        }
    })()

    return (
        <div
            style={{
                position: "fixed",
                backgroundColor: backgroundColor,
                color: textColor,
                padding: "20px 20px",
                borderRadius: "12px",
                display: "flex",
                alignItems: "center",
                boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
                width: "100%",
                maxWidth: "350px",
                zIndex: 1000,
                fontFamily: fontFamily,
                animation: "fadeInUp 0.5s ease-out",
                ...positionStyles,
            }}
        >
            {icon && (
                <span
                    style={{
                        marginRight: "20px",
                        display: "flex",
                        alignItems: "center",
                    }}
                >
                    <img
                        src={icon}
                        alt="icon"
                        style={{ width: iconSize, height: iconSize }}
                    />
                </span>
            )}
            <div style={{ flex: 1 }}>
                <h4
                    style={{
                        margin: 0,
                        fontSize: "16px",
                        fontWeight: "600",
                        color: textColor,
                        maxWidth: "90%",
                        paddingRight: "20px,",
                    }}
                >
                    {title}
                </h4>
                <p
                    style={{
                        margin: "4px 0 0",
                        fontSize: "14px",
                        color: textColor,
                        lineHeight: "1.4",
                        maxWidth: "90%",
                        paddingRight: "20px,",
                    }}
                >
                    {message}
                </p>
            </div>
            <button
                onClick={() => setShowToast(false)}
                style={{
                    position: "absolute",
                    top: "12px",
                    right: "12px",
                    width: "24px",
                    height: "24px",
                    background: "transparent",
                    border: "none",
                    color: textColor,
                    cursor: "pointer",
                    fontSize: "24px",
                    lineHeight: "24px",
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                }}
            >
                &times;
            </button>

            {/* Keyframe for fade-in and up animation */}
            <style>{`
                @keyframes fadeInUp {
                    from {
                        opacity: 0;
                        transform: translateY(20px);
                    }
                    to {
                        opacity: 1;
                        transform: translateY(0);
                    }
                }
            `}</style>
        </div>
    )
}

LandscapeToastWarning.defaultProps = {
    icon: "https://example.com/path-to-your-icon.png", // Replace with a valid icon URL
    iconSize: 24, // Default icon size
    title: "Better on portrait",
    message:
        "This site is optimized for portrait orientation on mobile devices. Please rotate your device for the best experience.",
    backgroundColor: "#34495e",
    textColor: "#ffffff",
    previewMode: true, // Enabled by default
    fontFamily: "Inter, sans-serif", // Default font family
    position: "Bottom Right", // Default position
    alertMode: "Landscape", // Default to landscape mode
}

addPropertyControls(LandscapeToastWarning, {
    icon: {
        type: ControlType.Image,
        title: "Icon",
    },
    iconSize: {
        type: ControlType.Number,
        title: "Icon Size",
        defaultValue: 24,
        min: 10,
        max: 50,
        unit: "px",
        displayStepper: true,
    },
    title: {
        type: ControlType.String,
        title: "Title",
    },
    message: {
        type: ControlType.String,
        title: "Message",
        displayTextArea: true,
    },
    backgroundColor: {
        type: ControlType.Color,
        title: "Background Color",
    },
    textColor: {
        type: ControlType.Color,
        title: "Text Color",
    },
    fontFamily: {
        type: ControlType.String,
        title: "Font Family",
        defaultValue: "Inter, sans-serif",
    },
    position: {
        type: ControlType.Enum,
        title: "Position",
        options: [
            "Top Left",
            "Top Center",
            "Top Right",
            "Bottom Left",
            "Bottom Center",
            "Bottom Right",
        ],
        optionTitles: [
            "Top Left",
            "Top Center",
            "Top Right",
            "Bottom Left",
            "Bottom Center",
            "Bottom Right",
        ],
        defaultValue: "Bottom Right",
    },
    alertMode: {
        type: ControlType.Enum,
        title: "Alert Mode",
        options: ["Landscape", "Portrait"],
        optionTitles: ["Landscape", "Portrait"],
        defaultValue: "Landscape",
    },
    previewMode: {
        type: ControlType.Boolean,
        title: "Preview Mode",
        defaultValue: true,
        enabledTitle: "On",
        disabledTitle: "Off",
    },
})

export default LandscapeToastWarning

CLICK TO COPY

// A custom Framer code override by Chris Kellett - Framerverse
// Get more components at www.framerverse.com
// Mobile Landscape Alert
// Version 1.0

import React, { useState, useEffect } from "react"
import { addPropertyControls, ControlType } from "framer"

function LandscapeToastWarning(props) {
    const {
        icon,
        iconSize,
        title,
        message,
        backgroundColor,
        textColor,
        previewMode,
        fontFamily,
        position,
        alertMode,
    } = props
    const [showToast, setShowToast] = useState(false)

    useEffect(() => {
        const checkOrientation = () => {
            const isMobile = window.innerWidth <= 768
            const isLandscape = window.innerWidth > window.innerHeight
            const shouldShow =
                previewMode ||
                (isMobile &&
                    ((alertMode === "Landscape" && isLandscape) ||
                        (alertMode === "Portrait" && !isLandscape)))
            setShowToast(shouldShow)
        }

        if (!previewMode) {
            checkOrientation()
            window.addEventListener("resize", checkOrientation)
            window.addEventListener("orientationchange", checkOrientation)

            return () => {
                window.removeEventListener("resize", checkOrientation)
                window.removeEventListener(
                    "orientationchange",
                    checkOrientation
                )
            }
        } else {
            setShowToast(true)
        }
    }, [previewMode, alertMode])

    if (!showToast) return null

    // Determine position styles based on the selected position prop
    const positionStyles = (() => {
        switch (position) {
            case "Top Left":
                return { top: "20px", left: "20px" }
            case "Top Center":
                return {
                    top: "20px",
                    left: "50%",
                    transform: "translateX(-50%)",
                }
            case "Top Right":
                return { top: "20px", right: "20px" }
            case "Bottom Left":
                return { bottom: "20px", left: "20px" }
            case "Bottom Center":
                return {
                    bottom: "20px",
                    left: "50%",
                    transform: "translateX(-50%)",
                }
            case "Bottom Right":
            default:
                return { bottom: "20px", right: "20px" }
        }
    })()

    return (
        <div
            style={{
                position: "fixed",
                backgroundColor: backgroundColor,
                color: textColor,
                padding: "20px 20px",
                borderRadius: "12px",
                display: "flex",
                alignItems: "center",
                boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
                width: "100%",
                maxWidth: "350px",
                zIndex: 1000,
                fontFamily: fontFamily,
                animation: "fadeInUp 0.5s ease-out",
                ...positionStyles,
            }}
        >
            {icon && (
                <span
                    style={{
                        marginRight: "20px",
                        display: "flex",
                        alignItems: "center",
                    }}
                >
                    <img
                        src={icon}
                        alt="icon"
                        style={{ width: iconSize, height: iconSize }}
                    />
                </span>
            )}
            <div style={{ flex: 1 }}>
                <h4
                    style={{
                        margin: 0,
                        fontSize: "16px",
                        fontWeight: "600",
                        color: textColor,
                        maxWidth: "90%",
                        paddingRight: "20px,",
                    }}
                >
                    {title}
                </h4>
                <p
                    style={{
                        margin: "4px 0 0",
                        fontSize: "14px",
                        color: textColor,
                        lineHeight: "1.4",
                        maxWidth: "90%",
                        paddingRight: "20px,",
                    }}
                >
                    {message}
                </p>
            </div>
            <button
                onClick={() => setShowToast(false)}
                style={{
                    position: "absolute",
                    top: "12px",
                    right: "12px",
                    width: "24px",
                    height: "24px",
                    background: "transparent",
                    border: "none",
                    color: textColor,
                    cursor: "pointer",
                    fontSize: "24px",
                    lineHeight: "24px",
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                }}
            >
                &times;
            </button>

            {/* Keyframe for fade-in and up animation */}
            <style>{`
                @keyframes fadeInUp {
                    from {
                        opacity: 0;
                        transform: translateY(20px);
                    }
                    to {
                        opacity: 1;
                        transform: translateY(0);
                    }
                }
            `}</style>
        </div>
    )
}

LandscapeToastWarning.defaultProps = {
    icon: "https://example.com/path-to-your-icon.png", // Replace with a valid icon URL
    iconSize: 24, // Default icon size
    title: "Better on portrait",
    message:
        "This site is optimized for portrait orientation on mobile devices. Please rotate your device for the best experience.",
    backgroundColor: "#34495e",
    textColor: "#ffffff",
    previewMode: true, // Enabled by default
    fontFamily: "Inter, sans-serif", // Default font family
    position: "Bottom Right", // Default position
    alertMode: "Landscape", // Default to landscape mode
}

addPropertyControls(LandscapeToastWarning, {
    icon: {
        type: ControlType.Image,
        title: "Icon",
    },
    iconSize: {
        type: ControlType.Number,
        title: "Icon Size",
        defaultValue: 24,
        min: 10,
        max: 50,
        unit: "px",
        displayStepper: true,
    },
    title: {
        type: ControlType.String,
        title: "Title",
    },
    message: {
        type: ControlType.String,
        title: "Message",
        displayTextArea: true,
    },
    backgroundColor: {
        type: ControlType.Color,
        title: "Background Color",
    },
    textColor: {
        type: ControlType.Color,
        title: "Text Color",
    },
    fontFamily: {
        type: ControlType.String,
        title: "Font Family",
        defaultValue: "Inter, sans-serif",
    },
    position: {
        type: ControlType.Enum,
        title: "Position",
        options: [
            "Top Left",
            "Top Center",
            "Top Right",
            "Bottom Left",
            "Bottom Center",
            "Bottom Right",
        ],
        optionTitles: [
            "Top Left",
            "Top Center",
            "Top Right",
            "Bottom Left",
            "Bottom Center",
            "Bottom Right",
        ],
        defaultValue: "Bottom Right",
    },
    alertMode: {
        type: ControlType.Enum,
        title: "Alert Mode",
        options: ["Landscape", "Portrait"],
        optionTitles: ["Landscape", "Portrait"],
        defaultValue: "Landscape",
    },
    previewMode: {
        type: ControlType.Boolean,
        title: "Preview Mode",
        defaultValue: true,
        enabledTitle: "On",
        disabledTitle: "Off",
    },
})

export default LandscapeToastWarning

CLICK TO COPY

What is it?

If your site works better in one orientation than another why not let your users know with this little component.

What is it?

If your site works better in one orientation than another why not let your users know with this little component.

What is it?

If your site works better in one orientation than another why not let your users know with this little component.

How to use.

Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.

How to use.

Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.

How to use.

Click in the code are below to copy the code to your clipboard. Then click the 'plus' button int the assets panel for 'Code'. Choose if its an overide or Component. Paste the code in and save.

Usage Licence

I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).

Usage Licence

I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).

Usage Licence

I'm happy for you to use this code in your projects, even templates. If you use it please keep my accreditation in the code. Please don't sell it as your own. (Hover for full licence).

Change Log

// Version 1.0

Figma to Framer

Support

If you need support first watch the help video above. If that does not help reach out to me on one of my social channels or use the contact form. As I am a team of one it may take a short while to get back to you. Please be patient, thanks.

Hope this helps. Good luck with your project.

More Framer resources.

Add a fully functional, responsive, configurable loan calculator to your project.

Real Loan Calculator

Add a fully functional, responsive, configurable loan calculator to your project.

Section

Add a fully functional, responsive, configurable loan calculator to your project.

Real Loan Calculator

Add a fully functional, responsive, configurable loan calculator to your project.

Section

Add a fully functional, responsive, configurable loan calculator to your project.

Real Loan Calculator

Add a fully functional, responsive, configurable loan calculator to your project.

Section

A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).

Starfield Generator

A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).

Code Component

A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).

Starfield Generator

A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).

Code Component

A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).

Starfield Generator

A niche component for creating a swirling Starfield, simple but great in the right scenario (like this site).

Code Component

Use this component and overide combo to create a swipe toggle that switches component variants.

Swipe Variant Changer

Use this component and overide combo to create a swipe toggle that switches component variants.

Code Override

Use this component and overide combo to create a swipe toggle that switches component variants.

Swipe Variant Changer

Use this component and overide combo to create a swipe toggle that switches component variants.

Code Override

Use this component and overide combo to create a swipe toggle that switches component variants.

Swipe Variant Changer

Use this component and overide combo to create a swipe toggle that switches component variants.

Code Override

Use a URL parameter to change the variant on the page you link to.

Change Variants with URL Parameters

Use a URL parameter to change the variant on the page you link to.

Code Override

Use a URL parameter to change the variant on the page you link to.

Change Variants with URL Parameters

Use a URL parameter to change the variant on the page you link to.

Code Override

Use a URL parameter to change the variant on the page you link to.

Change Variants with URL Parameters

Use a URL parameter to change the variant on the page you link to.

Code Override

Need a simple documentation system? This component adds auto linking contents list to a one page document system.

Simple Documentation Maker

Need a simple documentation system? This component adds auto linking contents list to a one page document system.

Code Component

Need a simple documentation system? This component adds auto linking contents list to a one page document system.

Simple Documentation Maker

Need a simple documentation system? This component adds auto linking contents list to a one page document system.

Code Component

Need a simple documentation system? This component adds auto linking contents list to a one page document system.

Simple Documentation Maker

Need a simple documentation system? This component adds auto linking contents list to a one page document system.

Code Component

Build simple form experiences that look, feel and work like a multi-step form.

Multi-step Form Experience

Build simple form experiences that look, feel and work like a multi-step form.

Section

Build simple form experiences that look, feel and work like a multi-step form.

Multi-step Form Experience

Build simple form experiences that look, feel and work like a multi-step form.

Section

Build simple form experiences that look, feel and work like a multi-step form.

Multi-step Form Experience

Build simple form experiences that look, feel and work like a multi-step form.

Section