diff --git a/src/app/commoncomponents/DataTransferMessageDelegate.qml b/src/app/commoncomponents/DataTransferMessageDelegate.qml
index d4dd426fa847f1262fa80b8de3d2dd95c4480049..6c0926274e15ff287632306a3cf95e3280fdcb80 100644
--- a/src/app/commoncomponents/DataTransferMessageDelegate.qml
+++ b/src/app/commoncomponents/DataTransferMessageDelegate.qml
@@ -326,8 +326,10 @@ Loader {
 
                     Component {
                         id: imageComp
+
                         Image {
                             id: img
+
                             anchors.right: isOutgoing ? parent.right : undefined
                             property real minSize: 192
                             property real maxSize: 256
@@ -346,6 +348,7 @@ Loader {
                                                                            innerContent.width - senderMargin))
                             width: adjustedWidth
                             height: Math.ceil(adjustedWidth / aspectRatio)
+
                             Rectangle {
                                 color: JamiTheme.previewImageBackgroundColor
                                 z: -1
diff --git a/src/app/commoncomponents/SBSMessageBase.qml b/src/app/commoncomponents/SBSMessageBase.qml
index a2d1bc3e1716f96c1b45f01f9ea94a98bba6fa63..343b4da434a3e78cddf8d32c4c7a5d398e65a139 100644
--- a/src/app/commoncomponents/SBSMessageBase.qml
+++ b/src/app/commoncomponents/SBSMessageBase.qml
@@ -32,7 +32,6 @@ Control {
     property alias avatarBlockWidth: avatarBlock.width
     property alias innerContent: innerContent
     property alias bubble: bubble
-    property alias selectAnimation: selectAnimation
     property real extraHeight: 0
 
     // these MUST be set but we won't use the 'required' keyword yet
@@ -145,6 +144,8 @@ Control {
 
                 MessageBubble {
                     id: bubble
+
+                    visible: !IsEmojiOnly
                     z:-1
                     out: isOutgoing
                     type: seq
@@ -166,15 +167,48 @@ Control {
                     height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0)
                 }
 
+                Rectangle {
+                    id: bg
+
+                    color: bubble.getBaseColor()
+                    anchors.fill: parent
+                    visible: false
+                }
+
                 SequentialAnimation {
                     id: selectAnimation
-                    ColorAnimation {
-                        target: bubble; property: "color"
-                        to: Qt.darker(bubble.getBaseColor(), 1.5); duration: 240
+
+                    PropertyAnimation {
+                        properties: "opacity"
+                        target: opacityMask
+                        from: 0
+                        to: 1
+                        duration: JamiTheme.longFadeDuration
                     }
-                    ColorAnimation {
-                        target: bubble; property: "color"
-                        to: bubble.getBaseColor(); duration: 240
+                    PropertyAnimation {
+                        properties: "opacity"
+                        target: opacityMask
+                        from: 1
+                        to: 0
+                        duration: JamiTheme.longFadeDuration
+                    }
+                }
+
+                OpacityMask {
+                    id: opacityMask
+
+                    opacity: 0
+                    anchors.fill: bubble
+                    source: bubble
+                    maskSource: bg
+                }
+
+                Connections {
+                    target: CurrentConversation
+                    function onScrollTo(id) {
+                        if (id !== root.id)
+                            return
+                        selectAnimation.start()
                     }
                 }
             }
diff --git a/src/app/commoncomponents/TextMessageDelegate.qml b/src/app/commoncomponents/TextMessageDelegate.qml
index 0177699767b9c880086e776e1f97173272c64a09..0cbe4b0d54f9a69dddd7ff5381725fb5a71c21fd 100644
--- a/src/app/commoncomponents/TextMessageDelegate.qml
+++ b/src/app/commoncomponents/TextMessageDelegate.qml
@@ -21,6 +21,7 @@ import QtQuick
 import QtQuick.Controls
 import QtQuick.Layouts
 import Qt5Compat.GraphicalEffects
+
 import net.jami.Models 1.1
 import net.jami.Adapters 1.1
 import net.jami.Constants 1.1
@@ -30,7 +31,9 @@ SBSMessageBase {
     id : root
 
     property bool isRemoteImage
+    property bool isEmojiOnly: IsEmojiOnly
     property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth
+
     isOutgoing: Author === ""
     author: Author
     readers: Readers
@@ -41,10 +44,15 @@ SBSMessageBase {
 
     innerContent.children: [
         TextEdit {
-            padding: JamiTheme.preferredMarginSize
+            id: textEditId
+
+            padding: isEmojiOnly ? 0 : JamiTheme.preferredMarginSize
             anchors.right: isOutgoing ? parent.right : undefined
+
             text: Body
-            horizontalAlignment: Text.AlignLeft
+
+            horizontalAlignment: isOutgoing ? Text.AlignLeft : Text.AlignRight
+
             width: {
                 if (extraContent.active)
                     Math.max(extraContent.width,
@@ -57,16 +65,31 @@ SBSMessageBase {
             height: implicitHeight
             wrapMode: Label.WrapAtWordBoundaryOrAnywhere
             selectByMouse: true
-            font.pixelSize: JamiTheme.chatviewFontSize
+            font.pixelSize: isEmojiOnly? JamiTheme.chatviewEmojiSize : JamiTheme.chatviewFontSize
+
             font.hintingPreference: Font.PreferNoHinting
             renderType: Text.NativeRendering
             textFormat: Text.MarkdownText
             onLinkHovered: root.hoveredLink = hoveredLink
             onLinkActivated: Qt.openUrlExternally(hoveredLink)
             readOnly: true
-            color: UtilsAdapter.luma(bubble.color) ?
-                       JamiTheme.chatviewTextColorLight :
-                       JamiTheme.chatviewTextColorDark
+            color: getBaseColor()
+
+            function getBaseColor() {
+                var baseColor
+                if (isEmojiOnly) {
+                    if (JamiTheme.darkTheme)
+                        baseColor = JamiTheme.chatviewTextColorLight
+                    else
+                        baseColor = JamiTheme.chatviewTextColorDark
+                } else {
+                    if (UtilsAdapter.luma(bubble.color))
+                        baseColor = JamiTheme.chatviewTextColorLight
+                    else
+                        baseColor = JamiTheme.chatviewTextColorDark
+                }
+                return baseColor
+            }
 
             TapHandler {
                 enabled: parent.selectedText.length > 0
@@ -104,6 +127,7 @@ SBSMessageBase {
                 }
                 AnimatedImage {
                     id: img
+
                     cache: false
                     source: isRemoteImage ?
                                 LinkPreviewInfo.url :
diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml
index 0bccb0fef408e2b5b3c811af3e3d068bd51f1b0d..5267a12e9aca8c7c3c297bac7182db12a5292d58 100644
--- a/src/app/constant/JamiTheme.qml
+++ b/src/app/constant/JamiTheme.qml
@@ -188,6 +188,7 @@ Item {
     property color chatviewTextColorLight: "#f0f0f0"
     property color chatviewTextColorDark: "#353637"
     property real chatviewFontSize: calcSize(15)
+    property real chatviewEmojiSize: calcSize(60)
     property color timestampColor: darkTheme ? "#bbb" : "#777"
     property color messageOutTxtColor: "#000000"
     property color messageInBgColor: darkTheme ? "#28b1ed" : "#e5e5e5"
diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml
index 0c4357035e22917a73793a72fb87890faffb24cf..ffc2c0125d299c533db8540cd29d346fbd6de3aa 100644
--- a/src/app/mainview/components/MessageListView.qml
+++ b/src/app/mainview/components/MessageListView.qml
@@ -166,9 +166,6 @@ JamiListView {
                 }
             }
             positionViewAtIndex(idx, ListView.Center)
-            var delegate = root.itemAtIndex(idx)
-            if (delegate.selectAnimation)
-                delegate.selectAnimation.start()
         }
     }
 
diff --git a/src/libclient/messagelistmodel.cpp b/src/libclient/messagelistmodel.cpp
index f796f6fdc79b0e1ee198f6028e02789318047806..8e3f0b1cba0806950f4ca05081294cdfb9647eee 100644
--- a/src/libclient/messagelistmodel.cpp
+++ b/src/libclient/messagelistmodel.cpp
@@ -357,6 +357,29 @@ MessageListModel::roleNames() const
     return roles;
 }
 
+bool
+MessageListModel::isOnlyEmoji(const QString& text) const
+{
+    auto codepointList = text.toUcs4();
+    for (QList<uint>::iterator it = codepointList.begin(); it != codepointList.end(); it++) {
+        auto cur = false;
+        if (*it == 20 or *it == 0x200D) {
+            cur = true;
+        } else if (0x1f000 <= *it && 0x1ffff >= *it) {
+            cur = true;
+        } else if (0x2600 <= *it && 0x27BF >= *it) {
+            cur = true;
+        } else if (0xFE00 <= *it && 0xFE0f >= *it) {
+            cur = true;
+        } else if (0xE0000 <= *it && 0xE007F >= *it) {
+            cur = true;
+        }
+        if (!cur)
+            return false;
+    }
+    return true;
+}
+
 QVariant
 MessageListModel::dataForItem(item_t item, int, int role) const
 {
@@ -401,6 +424,8 @@ MessageListModel::dataForItem(item_t item, int, int role) const
         return QVariant(item.second.commit["displayName"]);
     case Role::Readers:
         return QVariant(messageToReaders_[item.first]);
+    case Role::IsEmojiOnly:
+        return QVariant(isOnlyEmoji(item.second.body));
     default:
         return {};
     }
diff --git a/src/libclient/messagelistmodel.h b/src/libclient/messagelistmodel.h
index 88028550fbeda72f5ede99c39c01dc7422602099..2613276b73d4e5efe37b0012e45ce5851e5a140b 100644
--- a/src/libclient/messagelistmodel.h
+++ b/src/libclient/messagelistmodel.h
@@ -50,7 +50,8 @@ struct Info;
     X(ReplyToAuthor) \
     X(TotalSize) \
     X(TransferName) \
-    X(Readers)
+    X(Readers) \
+    X(IsEmojiOnly)
 
 namespace MessageList {
 Q_NAMESPACE
@@ -125,6 +126,7 @@ public:
     // these emission wrappers
     void emitDataChanged(iterator it, VectorInt roles = {});
     void emitDataChanged(const QString& msgId, VectorInt roles = {});
+    bool isOnlyEmoji(const QString& text) const;
 
     Q_SIGNAL void timestampUpdate();