diff --git a/client/web/divkit/src/components/image/Image.module.css b/client/web/divkit/src/components/image/Image.module.css index 060d5b244..31520dfea 100644 --- a/client/web/divkit/src/components/image/Image.module.css +++ b/client/web/divkit/src/components/image/Image.module.css @@ -42,7 +42,21 @@ display: block; } -.image_aspect .image__image { +.image_aspect-content .image__aspect-wrapper { + display: grid; + height: 0; + align-content: center; +} + +.image_aspect-content.image_aspect-valign_top .image__aspect-wrapper { + align-content: start; +} + +.image_aspect-content.image_aspect-valign_bottom .image__aspect-wrapper { + align-content: end; +} + +.image_aspect:not(.image_aspect-content) .image__image { position: absolute; top: 0; left: 0; diff --git a/client/web/divkit/src/components/image/Image.svelte b/client/web/divkit/src/components/image/Image.svelte index cd0a78b43..1e45692ee 100644 --- a/client/web/divkit/src/components/image/Image.svelte +++ b/client/web/divkit/src/components/image/Image.svelte @@ -53,7 +53,10 @@ // Exactly "none", "scale-down" would not match android let scale = 'none'; let position = '50% 50%'; + let aspectPaddingTop = '0'; let aspectPaddingBottom = '0'; + let aspectContent = false; + let aspectContentVAlign = 'center'; let tintColor: string | undefined = undefined; let tintMode: TintMode = 'source_in'; let svgFilterId = ''; @@ -70,6 +73,7 @@ $: origJson = componentContext.origJson; function rebind(): void { + aspectContent = false; scale = 'none'; position = '50% 50%'; tintMode = 'source_in'; @@ -166,9 +170,28 @@ $: alt = $jsonA11y?.description || ''; $: { + aspectContentVAlign = 'center'; + aspectPaddingTop = '0'; + aspectPaddingBottom = '0'; + const newRatio = $jsonAspect?.ratio; if (newRatio && isPositiveNumber(newRatio)) { - aspectPaddingBottom = (100 / Number(newRatio)).toFixed(2); + const height = 100 / Number(newRatio); + aspectContent = componentContext.json.width?.type === 'wrap_content'; + + if (aspectContent) { + if ($jsonPosition.content_alignment_vertical === 'top') { + aspectPaddingBottom = height.toFixed(2); + aspectContentVAlign = 'top'; + } else if ($jsonPosition.content_alignment_vertical === 'bottom') { + aspectPaddingTop = height.toFixed(2); + aspectContentVAlign = 'bottom'; + } else { + aspectPaddingTop = aspectPaddingBottom = (height / 2).toFixed(2); + } + } else { + aspectPaddingBottom = height.toFixed(2); + } } else { aspectPaddingBottom = '0'; } @@ -210,7 +233,9 @@ } $: mods = { - aspect: aspectPaddingBottom !== '0', + aspect: aspectPaddingBottom !== '0' || aspectPaddingTop !== '0', + 'aspect-content': aspectContent, + 'aspect-valign': aspectContentVAlign !== 'center' ? aspectContentVAlign : undefined, 'is-width-content': isWidthContent, 'is-height-content': isHeightContent, loaded: state === STATE_LOADED, @@ -263,7 +288,11 @@ {#key svgFilterId} {#if mods.aspect} - +