diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ee01ae26..969564520 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [Unreleased]
+
+### Added
+- Add CLI parameters `--truncate-owner-after` and `--truncate-owner-marker` (and equivalent
+  configuration fields) to truncate user and group names if they exceed a certain number
+  of characters (disabled by default).
+
 ## [v1.0.0] - 2023-08-25
 
 ### Added
@@ -391,7 +398,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Change the component alignment by using term_grid
 
 
-
+[Unreleased]: https://github.com/lsd-rs/lsd/compare/v1.0.0...HEAD
 [v1.0.0]: https://github.com/lsd-rs/lsd/compare/0.23.1...v1.0.0
 [0.23.1]: https://github.com/Peltoche/lsd/compare/0.23.0...0.23.1
 [0.23.0]: https://github.com/Peltoche/lsd/compare/0.22.0...0.23.0
diff --git a/README.md b/README.md
index f386aee88..ae46daafc 100644
--- a/README.md
+++ b/README.md
@@ -228,6 +228,15 @@ symlink-arrow: ⇒
 # Whether to display block headers.
 # Possible values: false, true
 header: false
+
+# == Truncate owner ==
+# How to truncate the username and group names for a file if they exceed a certain
+# number of characters.
+truncate-owner:
+  # Number of characters to keep. By default, no truncation is done (empty value).
+  after:
+  # String to be appended to a name if truncated.
+  marker: ""
 ```
 
 </details>
diff --git a/doc/lsd.md b/doc/lsd.md
index b86cdd0de..636913e75 100644
--- a/doc/lsd.md
+++ b/doc/lsd.md
@@ -140,6 +140,12 @@ lsd is a ls command with a lot of pretty colours and some other stuff to enrich
 `--header`
 : Display block headers
 
+`--truncate-owner-after`
+: Truncate the user and group names if they exceed a certain number of characters
+
+`--truncate-owner-marker`
+: Truncation marker appended to a truncated user or group name
+
 # ARGS
 
 `<FILE>...`
diff --git a/src/app.rs b/src/app.rs
index bd6defaeb..a288eba52 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -176,6 +176,14 @@ pub struct Cli {
     #[arg(long)]
     pub header: bool,
 
+    /// Truncate the user and group names if they exceed a certain number of characters
+    #[arg(long, value_name = "NUM")]
+    pub truncate_owner_after: Option<usize>,
+
+    /// Truncation marker appended to a truncated user or group name
+    #[arg(long, value_name = "STR")]
+    pub truncate_owner_marker: Option<String>,
+
     /// Includes files with the windows system protection flag set.
     /// This is the same as --all on other platforms
     #[arg(long, hide = !cfg!(windows))]
diff --git a/src/config_file.rs b/src/config_file.rs
index c9392c838..f6f9d68fd 100644
--- a/src/config_file.rs
+++ b/src/config_file.rs
@@ -45,6 +45,7 @@ pub struct Config {
     pub symlink_arrow: Option<String>,
     pub hyperlink: Option<HyperlinkOption>,
     pub header: Option<bool>,
+    pub truncate_owner: Option<TruncateOwner>,
 }
 
 #[derive(Eq, PartialEq, Debug, Deserialize)]
@@ -74,6 +75,12 @@ pub struct Sorting {
     pub dir_grouping: Option<DirGrouping>,
 }
 
+#[derive(Eq, PartialEq, Debug, Deserialize)]
+pub struct TruncateOwner {
+    pub after: Option<usize>,
+    pub marker: Option<String>,
+}
+
 impl Config {
     /// This constructs a Config struct with all None
     pub fn with_none() -> Self {
@@ -97,6 +104,7 @@ impl Config {
             symlink_arrow: None,
             hyperlink: None,
             header: None,
+            truncate_owner: None,
         }
     }
 
@@ -323,6 +331,15 @@ hyperlink: never
 # == Symlink arrow ==
 # Specifies how the symlink arrow display, chars in both ascii and utf8
 symlink-arrow: ⇒
+
+# == Truncate owner ==
+# How to truncate the username and group name for the file if they exceed a
+# certain number of characters.
+truncate-owner:
+  # Number of characters to keep. By default, no truncation is done (empty value).
+  after:
+  # String to be appended to a name if truncated.
+  marker: ""
 "#;
 
 #[cfg(test)]
@@ -389,6 +406,10 @@ mod tests {
                 symlink_arrow: Some("⇒".into()),
                 hyperlink: Some(HyperlinkOption::Never),
                 header: None,
+                truncate_owner: Some(config_file::TruncateOwner {
+                    after: None,
+                    marker: Some("".to_string()),
+                }),
             },
             c
         );
diff --git a/src/display.rs b/src/display.rs
index 6fea6e9a3..bf788faeb 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -355,11 +355,11 @@ fn get_output(
                 ]);
             }
             Block::User => block_vec.push(match &meta.owner {
-                Some(owner) => owner.render_user(colors),
+                Some(owner) => owner.render_user(colors, flags),
                 None => colorize_missing("?"),
             }),
             Block::Group => block_vec.push(match &meta.owner {
-                Some(owner) => owner.render_group(colors),
+                Some(owner) => owner.render_group(colors, flags),
                 None => colorize_missing("?"),
             }),
             Block::Context => block_vec.push(match &meta.access_control {
diff --git a/src/flags.rs b/src/flags.rs
index a73ac6534..e02deb9b6 100644
--- a/src/flags.rs
+++ b/src/flags.rs
@@ -16,6 +16,7 @@ pub mod sorting;
 pub mod symlink_arrow;
 pub mod symlinks;
 pub mod total_size;
+pub mod truncate_owner;
 
 pub use blocks::Blocks;
 pub use color::Color;
@@ -42,6 +43,7 @@ pub use sorting::Sorting;
 pub use symlink_arrow::SymlinkArrow;
 pub use symlinks::NoSymlink;
 pub use total_size::TotalSize;
+pub use truncate_owner::TruncateOwner;
 
 use crate::app::Cli;
 use crate::config_file::Config;
@@ -72,6 +74,7 @@ pub struct Flags {
     pub symlink_arrow: SymlinkArrow,
     pub hyperlink: HyperlinkOption,
     pub header: Header,
+    pub truncate_owner: TruncateOwner,
     pub should_quote: bool,
 }
 
@@ -102,6 +105,7 @@ impl Flags {
             symlink_arrow: SymlinkArrow::configure_from(cli, config),
             hyperlink: HyperlinkOption::configure_from(cli, config),
             header: Header::configure_from(cli, config),
+            truncate_owner: TruncateOwner::configure_from(cli, config),
             should_quote: true,
         })
     }
diff --git a/src/flags/truncate_owner.rs b/src/flags/truncate_owner.rs
new file mode 100644
index 000000000..807dc4012
--- /dev/null
+++ b/src/flags/truncate_owner.rs
@@ -0,0 +1,120 @@
+//! This module defines the [TruncateOwner] flag. To set it up from [Cli], a [Config] and its
+//! [Default] value, use the [configure_from](Configurable::configure_from) method.
+
+use super::Configurable;
+use crate::app::Cli;
+
+use crate::config_file::Config;
+
+/// The flag showing how to truncate user and group names.
+#[derive(Clone, Debug, PartialEq, Eq, Default)]
+pub struct TruncateOwner {
+    pub after: Option<usize>,
+    pub marker: Option<String>,
+}
+
+impl Configurable<Self> for TruncateOwner {
+    /// Get a potential `TruncateOwner` value from [Cli].
+    ///
+    /// If the "header" argument is passed, this returns a `TruncateOwner` with value `true` in a
+    /// [Some]. Otherwise this returns [None].
+    fn from_cli(cli: &Cli) -> Option<Self> {
+        match (cli.truncate_owner_after, cli.truncate_owner_marker.clone()) {
+            (None, None) => None,
+            (after, marker) => Some(Self { after, marker }),
+        }
+    }
+
+    /// Get a potential `TruncateOwner` value from a [Config].
+    ///
+    /// If the `Config::truncate_owner` has value,
+    /// this returns it as the value of the `TruncateOwner`, in a [Some].
+    /// Otherwise this returns [None].
+    fn from_config(config: &Config) -> Option<Self> {
+        config.truncate_owner.as_ref().map(|c| Self {
+            after: c.after,
+            marker: c.marker.clone(),
+        })
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use clap::Parser;
+
+    use super::TruncateOwner;
+
+    use crate::app::Cli;
+    use crate::config_file::{self, Config};
+    use crate::flags::Configurable;
+
+    #[test]
+    fn test_from_cli_none() {
+        let argv = ["lsd"];
+        let cli = Cli::try_parse_from(argv).unwrap();
+        assert_eq!(None, TruncateOwner::from_cli(&cli));
+    }
+
+    #[test]
+    fn test_from_cli_after_some() {
+        let argv = ["lsd", "--truncate-owner-after", "1"];
+        let cli = Cli::try_parse_from(argv).unwrap();
+        assert_eq!(
+            Some(TruncateOwner {
+                after: Some(1),
+                marker: None,
+            }),
+            TruncateOwner::from_cli(&cli)
+        );
+    }
+
+    #[test]
+    fn test_from_cli_marker_some() {
+        let argv = ["lsd", "--truncate-owner-marker", "…"];
+        let cli = Cli::try_parse_from(argv).unwrap();
+        assert_eq!(
+            Some(TruncateOwner {
+                after: None,
+                marker: Some("…".to_string()),
+            }),
+            TruncateOwner::from_cli(&cli)
+        );
+    }
+
+    #[test]
+    fn test_from_config_none() {
+        assert_eq!(None, TruncateOwner::from_config(&Config::with_none()));
+    }
+
+    #[test]
+    fn test_from_config_all_fields_none() {
+        let mut c = Config::with_none();
+        c.truncate_owner = Some(config_file::TruncateOwner {
+            after: None,
+            marker: None,
+        });
+        assert_eq!(
+            Some(TruncateOwner {
+                after: None,
+                marker: None,
+            }),
+            TruncateOwner::from_config(&c)
+        );
+    }
+
+    #[test]
+    fn test_from_config_all_fields_some() {
+        let mut c = Config::with_none();
+        c.truncate_owner = Some(config_file::TruncateOwner {
+            after: Some(1),
+            marker: Some(">".to_string()),
+        });
+        assert_eq!(
+            Some(TruncateOwner {
+                after: Some(1),
+                marker: Some(">".to_string()),
+            }),
+            TruncateOwner::from_config(&c)
+        );
+    }
+}
diff --git a/src/meta/owner.rs b/src/meta/owner.rs
index ea48736af..4c54df318 100644
--- a/src/meta/owner.rs
+++ b/src/meta/owner.rs
@@ -1,4 +1,5 @@
 use crate::color::{ColoredString, Colors, Elem};
+use crate::Flags;
 #[cfg(unix)]
 use std::fs::Metadata;
 
@@ -35,12 +36,72 @@ impl From<&Metadata> for Owner {
     }
 }
 
+fn truncate(input: &str, after: Option<usize>, marker: Option<String>) -> String {
+    let mut output = input.to_string();
+
+    if let Some(after) = after {
+        if output.len() > after {
+            output.truncate(after);
+
+            if let Some(marker) = marker {
+                output.push_str(&marker);
+            }
+        }
+    }
+
+    output
+}
+
 impl Owner {
-    pub fn render_user(&self, colors: &Colors) -> ColoredString {
-        colors.colorize(self.user.clone(), &Elem::User)
+    pub fn render_user(&self, colors: &Colors, flags: &Flags) -> ColoredString {
+        colors.colorize(
+            truncate(
+                &self.user,
+                flags.truncate_owner.after,
+                flags.truncate_owner.marker.clone(),
+            ),
+            &Elem::User,
+        )
+    }
+
+    pub fn render_group(&self, colors: &Colors, flags: &Flags) -> ColoredString {
+        colors.colorize(
+            truncate(
+                &self.group,
+                flags.truncate_owner.after,
+                flags.truncate_owner.marker.clone(),
+            ),
+            &Elem::Group,
+        )
+    }
+}
+
+#[cfg(test)]
+mod test_truncate {
+    use crate::meta::owner::truncate;
+
+    #[test]
+    fn test_none() {
+        assert_eq!("a", truncate("a", None, None));
+    }
+
+    #[test]
+    fn test_unchanged_without_marker() {
+        assert_eq!("a", truncate("a", Some(1), None));
+    }
+
+    #[test]
+    fn test_unchanged_with_marker() {
+        assert_eq!("a", truncate("a", Some(1), Some("…".to_string())));
+    }
+
+    #[test]
+    fn test_truncated_without_marker() {
+        assert_eq!("a", truncate("ab", Some(1), None));
     }
 
-    pub fn render_group(&self, colors: &Colors) -> ColoredString {
-        colors.colorize(self.group.clone(), &Elem::Group)
+    #[test]
+    fn test_truncated_with_marker() {
+        assert_eq!("a…", truncate("ab", Some(1), Some("…".to_string())));
     }
 }
diff --git a/tests/integration.rs b/tests/integration.rs
index a43ce3565..f2000577a 100644
--- a/tests/integration.rs
+++ b/tests/integration.rs
@@ -659,6 +659,24 @@ fn test_upper_case_ext_icon_match() {
         .stdout(predicate::str::contains("\u{f410}"));
 }
 
+#[cfg(unix)]
+#[test]
+fn test_truncate_owner() {
+    let dir = tempdir();
+    dir.child("foo").touch().unwrap();
+
+    cmd()
+        .arg("-l")
+        .arg("--ignore-config")
+        .arg("--truncate-owner-after")
+        .arg("1")
+        .arg("--truncate-owner-marker")
+        .arg("…")
+        .arg(dir.path())
+        .assert()
+        .stdout(predicate::str::is_match(" .… .… ").unwrap());
+}
+
 #[cfg(unix)]
 #[test]
 fn test_custom_config_file_parsing() {