diff --git a/packages/vkui/src/components/ImageBase/ImageBase.module.css b/packages/vkui/src/components/ImageBase/ImageBase.module.css
index 85b435c010..3ddf965ac7 100644
--- a/packages/vkui/src/components/ImageBase/ImageBase.module.css
+++ b/packages/vkui/src/components/ImageBase/ImageBase.module.css
@@ -71,6 +71,15 @@
object-fit: scale-down;
}
+.withObjectPosition {
+ --vkui_internal--ImageBase_object_position_default: 50% 50%;
+
+ object-position: var(
+ --vkui_internal--ImageBase_object_position,
+ var(--vkui_internal--ImageBase_object_position_default)
+ );
+}
+
.loaded .img {
visibility: visible;
}
diff --git a/packages/vkui/src/components/ImageBase/ImageBase.test.tsx b/packages/vkui/src/components/ImageBase/ImageBase.test.tsx
index 80b16256a3..f36b0c1c45 100644
--- a/packages/vkui/src/components/ImageBase/ImageBase.test.tsx
+++ b/packages/vkui/src/components/ImageBase/ImageBase.test.tsx
@@ -220,6 +220,15 @@ describe(ImageBase, () => {
render(} size={28} />);
expect(logStub).toHaveBeenCalledTimes(1);
});
+
+ it('should apply custom objectPosition style', () => {
+ render();
+
+ expect(getImageBaseImgEl()).toHaveClass(styles.withObjectPosition);
+ expect(getImageBaseImgEl()).toHaveStyle({
+ '--vkui_internal--ImageBase_object_position': 'center bottom',
+ });
+ });
});
describe(getOverlayIconSizeByImageBaseSize, () => {
diff --git a/packages/vkui/src/components/ImageBase/ImageBase.tsx b/packages/vkui/src/components/ImageBase/ImageBase.tsx
index d8c1a9f279..5fd019b0ae 100644
--- a/packages/vkui/src/components/ImageBase/ImageBase.tsx
+++ b/packages/vkui/src/components/ImageBase/ImageBase.tsx
@@ -3,10 +3,17 @@
import { useRef } from 'react';
import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
+import { mergeStyle } from '../../helpers/mergeStyle';
import { useExternRef } from '../../hooks/useExternRef';
import { minOr } from '../../lib/comparing';
import { getFetchPriorityProp } from '../../lib/utils';
-import type { AnchorHTMLAttributesOnly, HasRef, HasRootRef, LiteralUnion } from '../../types';
+import type {
+ AnchorHTMLAttributesOnly,
+ CSSCustomProperties,
+ HasRef,
+ HasRootRef,
+ LiteralUnion,
+} from '../../types';
import { Clickable } from '../Clickable/Clickable';
import { ImageBaseBadge, type ImageBaseBadgeProps } from './ImageBaseBadge/ImageBaseBadge';
import {
@@ -94,6 +101,11 @@ export interface ImageBaseProps
* Подробнее можно почитать в [документации](https://developer.mozilla.org/ru/docs/Web/CSS/object-fit)
*/
objectFit?: React.CSSProperties['objectFit'];
+ /**
+ * Пользовательское значения стиля object-position
+ * Подробнее можно почитать в [документации](https://developer.mozilla.org/ru/docs/Web/CSS/object-position)
+ */
+ objectPosition?: React.CSSProperties['objectPosition'];
/**
* Флаг для сохранения пропорций картинки.
* Для корректной работы необходимо задать размеры хотя бы одной стороны картинки
@@ -160,6 +172,7 @@ export const ImageBase: React.FC & {
onError,
withTransparentBackground,
objectFit = 'cover',
+ objectPosition,
keepAspectRatio = false,
getRootRef,
...restProps
@@ -238,6 +251,19 @@ export const ImageBase: React.FC & {
[size],
);
+ const imgStyles: CSSCustomProperties | undefined = objectPosition
+ ? {
+ '--vkui_internal--ImageBase_object_position': objectPosition,
+ }
+ : undefined;
+
+ const keepAspectRationStyles = keepAspectRatio
+ ? {
+ width: widthImg || width,
+ height: heightImg || height,
+ }
+ : undefined;
+
return (
& {
className={classNames(
styles.img,
getObjectFitClassName(objectFit),
+ objectPosition && styles.withObjectPosition,
keepAspectRatio && styles.imgKeepRatio,
)}
crossOrigin={crossOrigin}
decoding={decoding}
loading={loading}
referrerPolicy={referrerPolicy}
- style={
- keepAspectRatio
- ? {
- width: widthImg || width,
- height: heightImg || height,
- }
- : undefined
- }
+ style={mergeStyle(keepAspectRationStyles, imgStyles)}
sizes={sizes}
src={src}
srcSet={srcSet}