Social Safe Zones

social-safe-zones.tsximportReact , {forwardRef ,useId ,useImperativeHandle ,useRef } from 'react'; import {CanvasImage ,Interactive ,Sequence , typeInteractiveBaseProps , typeInteractiveTransformProps , typeInteractivitySchema , typeSequenceControls , } from 'remotion'; typeSocialSafeZonesProps =InteractiveBaseProps &InteractiveTransformProps & { readonlyoverlayOpacity ?: number; readonlyplatform ?: 'instagram' | 'tiktok'; readonlyshowInterface ?: boolean; }; constsocialSafeZonesSchema = { ...Interactive .baseSchema ,platform : {type : 'enum',default : 'instagram',description : 'Platform',keyframable : false,variants : {tiktok : {}, }, },showInterface : {type : 'boolean',default : true,description : 'Show interface reference',keyframable : false, },overlayOpacity : {type : 'number',min : 0,max : 1,step : 0.05,default : 0.45,description : 'Unsafe area opacity',hiddenFromList : false,keyframable : false, }, } asconst satisfiesInteractivitySchema ; constSocialSafeZonesInner =forwardRef <HTMLDivElement ,SocialSafeZonesProps & { readonlycontrols :SequenceControls | undefined; } >( ( {controls ,name ,overlayOpacity = 0.45,platform = 'instagram',showInterface = true,style , ...sequenceProps },ref , ) => { constoutlineRef =useRef <HTMLDivElement >(null); constmaskId = `social-safe-zone-${useId ().replaceAll (':', '')}`;useImperativeHandle (ref , () =>outlineRef .current asHTMLDivElement , []); // Both paths and interface references are measured from representative // iOS captures of full-green videos, rather than inferred from platform // marketing material. Author-specific text and avatars were replaced in // the transparent interface images. // // TikTok: The 1290×2293 video region at y=139 in tiktok-layout.png was // mapped to 1080×1920. The path clears the search UI (ending at y=132), // the action rail (starting at x=949, y=803), and captions (y=1749). // // Instagram: The 1290×2550 Reels viewport in reels-layout.png displays a // 9:16 video with cover sizing. Mapping it back to 1080×1920 leaves the // visible source between x=54 and x=1026. The path clears the top controls // (ending at y=212), action rail (starting at x=927, y=1114), and captions // (y=1726). constsafeAreaPath =platform === 'tiktok' ? 'M24 160 H1050 V780 H930 V1715 H24 Z' : 'M55 235 H1025 V1090 H900 V1700 H55 Z'; return ( <Sequence layout ="none" {...sequenceProps }controls ={controls }name ={name ?? '<SocialSafeZones>'}outlineRef ={outlineRef } > <div ref ={outlineRef }style ={{ ...style ,height : 1920,left : 0,pointerEvents : 'none',position : 'absolute',top : 0,width : 1080,zIndex : 2147483647, }} > <svg aria-hidden ="true"height ="100%"preserveAspectRatio ="xMidYMid meet"viewBox ="0 0 1080 1920"width ="100%" > <defs > <mask height ="1920"id ={maskId }maskUnits ="userSpaceOnUse"width ="1080"x ="0"y ="0" > <rect fill ="white"height ="1920"width ="1080" /> <path d ={safeAreaPath }fill ="black" /> </mask > </defs > <rect fill ="#ff3158"height ="1920"mask ={`url(#${maskId })`}opacity ={overlayOpacity }width ="1080" /> <path d ={safeAreaPath }fill ="none"stroke ="#c8ff3d"strokeDasharray ="22 16"strokeWidth ="8" /> </svg > {showInterface ? ( <CanvasImage aria-hidden ="true"fit ="contain"height ={1920}src ={platform === 'tiktok' ? 'https://remotion.media/elements/social-safe-zones/tiktok-interface.png' : 'https://remotion.media/elements/social-safe-zones/instagram-reels-interface-v3.png' }style ={{height : '100%',left : 0,position : 'absolute',top : 0,width : '100%', }}width ={1080} /> ) : null} </div > </Sequence > ); }, ); export constSocialSafeZones =Interactive .withSchema ({Component :SocialSafeZonesInner ,componentName : '<SocialSafeZones>',componentIdentity : null,schema :socialSafeZonesSchema ,supportsEffects : false, }) asReact .FC <SocialSafeZonesProps >;
Accuracy
The presets were measured at 9:16 from representative iOS captures of full-green videos in TikTok and Instagram Reels. The interface references are transparent images extracted from those captures, rather than redrawn approximations. Author-specific text and avatars were replaced with generic content. The Element has fixed 1080 × 1920 dimensions to preserve the calibrated geometry.
Live interfaces can vary by device, app version, locale, account state, caption length, and placement. Treat the clear region as a capture-calibrated reference, not a guarantee from either platform. The guide is rendered like any other Element, so hide or remove it when it should not appear in the final video.