diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js
index 68a449a924607ef34c00f6e98bd880a41b955e8d..13deb446c1cd55660a6edfff3ec2b3cc291b14e1 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -469,9 +469,18 @@ var ListRenderer = BasicRenderer.extend({
         var self = this;
         var nodeWithoutWidth = Object.assign({}, node);
         delete nodeWithoutWidth.attrs.width;
+
+        let extraClass = '';
+        if (node.attrs.icon) {
+            // if there is an icon, we force the btn-link style, unless a btn-xxx
+            // style class is explicitely provided
+            const btnStyleRegex = /\bbtn-(primary|secondary|link|success|info|warning|danger)\b/;
+            if (!btnStyleRegex.test(nodeWithoutWidth.attrs.class)) {
+                extraClass = 'btn-link o_icon_button';
+            }
+        }
         var $button = viewUtils.renderButtonFromNode(nodeWithoutWidth, {
-            extraClass: node.attrs.icon ? 'o_icon_button' : undefined,
-            textAsTitle: !!node.attrs.icon,
+            extraClass: extraClass,
         });
         this._handleAttributes($button, node);
         this._registerModifiers(node, record, $button);
diff --git a/addons/web/static/src/scss/list_view.scss b/addons/web/static/src/scss/list_view.scss
index a9076270ed2996aa94dd0f3ba97357a35d737a6d..4c0633cf0f3ba3070282274d5bbf2fb849977fd2 100644
--- a/addons/web/static/src/scss/list_view.scss
+++ b/addons/web/static/src/scss/list_view.scss
@@ -42,6 +42,9 @@
                 width: 17px;
                 height: 17px;
             }
+            &.o_list_button .o_button_icon {
+                margin-right: 3px;
+            }
         }
 
         tfoot {
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index 785b3864e8d9e654412ee69489e3a087af35f86e..913d75ed8bfd63936a70ca0d9ab5c091c837d63b 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -277,6 +277,33 @@ QUnit.module('Views', {
         list.destroy();
     });
 
+    QUnit.test('list view with icon buttons', async function (assert) {
+        assert.expect(5);
+
+        this.data.foo.records.splice(1);
+
+        const list = await createView({
+            View: ListView,
+            model: 'foo',
+            data: this.data,
+            arch: `
+                <tree>
+                    <button name="x" type="object" icon="fa-asterisk"/>
+                    <button name="x" type="object" icon="fa-star" class="o_yeah"/>
+                    <button name="x" type="object" icon="fa-refresh" string="Refresh" class="o_yeah"/>
+                    <button name="x" type="object" icon="fa-exclamation" string="Danger" class="o_yeah btn-danger"/>
+                </tree>`,
+        });
+
+        assert.containsOnce(list, 'button.btn.btn-link i.fa.fa-asterisk');
+        assert.containsOnce(list, 'button.btn.btn-link.o_yeah i.fa.fa-star');
+        assert.containsOnce(list, 'button.btn.btn-link.o_yeah:contains("Refresh") i.fa.fa-refresh');
+        assert.containsOnce(list, 'button.btn.btn-danger.o_yeah:contains("Danger") i.fa.fa-exclamation');
+        assert.containsNone(list, 'button.btn.btn-link.btn-danger');
+
+        list.destroy();
+    });
+
     QUnit.test('simple editable rendering', async function (assert) {
         assert.expect(15);