diff --git a/NAMESPACE b/NAMESPACE
index fa189445..59d3cea4 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -11,6 +11,8 @@ export(tpar)
 export(type_boxplot)
 export(type_errorbar)
 export(type_glm)
+export(type_hist)
+export(type_histogram)
 export(type_jitter)
 export(type_lm)
 export(type_loess)
diff --git a/NEWS.md b/NEWS.md
index 49507140..0c5068c9 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -9,23 +9,41 @@ where the formatting is also better._
 
 Breaking changes:
 
-* Type-specific arguments are no longer passed through the main function via
-`...`. Instead, they are now passed through a dedicated `type_*()` functions in
-the `type` argument.
+- Type-specific arguments (i.e., affecting the default behaviour of a certain
+plot type) should no longer be passed via `...` in the main plotting function.
+Instead, these additional arguments must now be passed explicitly as part of the
+corresponding `type_*()` function in the `type` argument. So, for example, you
+should now use `plt(Nile, type = type_histogram(breaks = 30))` instead of
+`plt(Nile, type = "histogram", breaks = 30)` if you wanted to adjust the number
+of breaks. More details are provided below and also in the new dedicated
+[Plot types vignette](https://grantmcdermott.com/tinyplot/vignettes/types.html).
+The essential idea is that shortcut character types (here: `"histogram"`) all
+still work, but are deliberately limited to default behaviour. In contrast, the
+functional equivalents (here: `type_histogram()`) are where we can customize
+behaviour by passing appropriate arguments. We're sorry to introduce a breaking
+change, but this new approach should ensure that users have better control of
+how their plots behave, and avoids guesswork on our side.
 
 New features:
 
+- Alongside the standard character shortcuts (`"p"`, `"l"`, etc.), the `type`
+argument now accepts functional `type_*()` equivalents. These functional plot
+types enable a variety of additional features. (#222 @vincentarelbundock)
+  - New model-based plot types:
+    - `type_glm()` (shortcut: `"glm"`)
+    - `type_lm()` (shortcut: `"lm"`)
+    - `type_loess()` (shortcut: `"loess"`)
+  - Explicit argument passing for modified behaviour type
+  (e.g., `type_lm(se = FALSE)`).
+  - Users can define their own custom types by creating `type_<typename>()`
+  functions.
+  - More details are provided in the dedicated
+  [Plot types vignette](https://grantmcdermott.com/tinyplot/vignettes/types.html)
+  on the website.
 - The new `flip` argument allows for easily flipping (swapping) the orientation
   of the x and y axes. This should work regardless of plot type, e.g.
   `plt(~Sepal.Length | Species, data = iris, type = "density", flip = TRUE)`.
   (#216 @grantmcdermott)
-- New plot types added in #222:
-    - `type_glm()` (shortcut: `"glm"`)
-    - `type_lm()` (shortcut: `"lm"`)
-    - `type_loess()` (shortcut: `"loess"`)
-- Custom types can now be defined by users by creating `type_typename()`
-  functions. (#222 @vincentarelbundock)
-- Types vignette on the website. (#222 @vincentarelbundock)
 
 Bug fixes:
 
diff --git a/R/tinyplot.R b/R/tinyplot.R
index 4e0361cd..a5d3dd57 100644
--- a/R/tinyplot.R
+++ b/R/tinyplot.R
@@ -290,9 +290,7 @@
 #'  specified.
 #' @param xaxt,yaxt character specifying the type of x-axis and y-axis, respectively.
 #'   See `axes` for the possible values.
-#' @param ... other graphical parameters (see \code{\link[graphics]{par}}), or
-#'   arguments passed to the relevant plot type (e.g., `breaks` for
-#'   `type = "histogram"`, or `varwidth` for `type = "boxplot"`). 
+#' @param ... other graphical parameters (see \code{\link[graphics]{par}}). 
 #'
 #' @returns No return value, called for side effect of producing a plot.
 #'   
@@ -1216,7 +1214,8 @@ tinyplot.formula = function(
   }
 
   ## nice axis and legend labels
-  if (!is.null(type) && isTRUE(type %in% c("hist", "histogram"))) {
+  hist_type = (is.atomic(type) && type %in% c("hist", "histogram")) || (!is.atomic(type) && identical(type$name, "histogram"))
+  if (!is.null(type) && hist_type) {
     if (is.null(ylab)) ylab = "Frequency"
     if (is.null(xlab)) xlab = xnam
   } else if (is.null(y)) {
diff --git a/R/type_histogram.R b/R/type_histogram.R
index 0759c883..5a087d43 100644
--- a/R/type_histogram.R
+++ b/R/type_histogram.R
@@ -1,17 +1,39 @@
-type_histogram = function() {
+#' Histogram type
+#' 
+#' @md
+#' @description Type function for histogram plots. `type_hist` is an alias for
+#'   `type_histogram`.
+#' @param breaks Passed to \code{\link[graphics]{hist}}. One of:
+#' - a vector giving the breakpoints between histogram cells,
+#' - a function to compute the vector of breakpoints,
+#' - a single number giving the number of cells for the histogram,
+#' - a character string naming an algorithm to compute the number of cells (see ‘Details’ of \code{\link[graphics]{hist}}),
+#' - a function to compute the number of cells.
+#' In the last three cases the number is a suggestion only; as the breakpoints
+#' will be set to pretty values, the number is limited to 1e6 (with a warning if
+#' it was larger). If breaks is a function, the x vector is supplied to it as
+#' the only argument (and the number of breaks is only limited by the amount of
+#' available memory).
+#' @export
+type_histogram = function(breaks = "Sturges") {
     out = list(
-        data = data_histogram(),
+        data = data_histogram(breaks = breaks),
         draw = draw_rect(),
         name = "histogram"
     )
     class(out) = "tinyplot_type"
     return(out)
 }
+#' @export
+#' @name type_hist
+#' @rdname type_histogram
+type_hist = type_histogram
 
 
-data_histogram = function() {
-    fun = function(by, facet, ylab, col, bg, ribbon.alpha, datapoints, breaks = NULL, ...) {
-        hbreaks = ifelse(!is.null(breaks), breaks, "Sturges")
+data_histogram = function(breaks = "Sturges") {
+    hbreaks = breaks
+    fun = function(by, facet, ylab, col, bg, ribbon.alpha, datapoints, .breaks = hbreaks, ...) {
+        hbreaks = ifelse(!is.null(.breaks), .breaks, "Sturges")
 
         if (is.null(ylab)) ylab = "Frequency"
         if (is.null(by) && is.null(palette)) {
diff --git a/inst/tinytest/test-histogram.R b/inst/tinytest/test-histogram.R
index 268131e5..719dc89e 100644
--- a/inst/tinytest/test-histogram.R
+++ b/inst/tinytest/test-histogram.R
@@ -21,8 +21,9 @@ f = function() {
   with(
     iris,
     plt(
-      Petal.Length, by = Species, type = "hist",
-      fill = 0.4, breaks = 30, palette = "classic"
+      Petal.Length, by = Species,
+      type = type_histogram(breaks = 30),
+      fill = 0.4, palette = "classic"
     )
   )
 }
@@ -42,8 +43,9 @@ f = function() {
   with(
     transform(iris, long_sepal = paste("Long sepal:", Sepal.Length > mean(Sepal.Length))),
     plt(
-      Petal.Length, by = Species, facet = long_sepal, type = "hist",
-      fill = 0.4, breaks = 30, palette = "classic", frame = FALSE, grid = TRUE
+      Petal.Length, by = Species, facet = long_sepal,
+      type = type_histogram(breaks = 30),
+      fill = 0.4, palette = "classic", frame = FALSE, grid = TRUE
     )
   )
 }
@@ -54,8 +56,9 @@ f = function() {
     ~Petal.Length | Species,
     data = transform(iris, long_sepal = paste("Long sepal:", Sepal.Length > mean(Sepal.Length))),
     facet = ~long_sepal,
-    type = "hist", fill = 0.4, 
-    breaks = 30, palette = "classic", frame = FALSE, grid = TRUE,
+    type = type_histogram(breaks = 30),
+    fill = 0.4,
+    palette = "classic", frame = FALSE, grid = TRUE,
   )
 }
 expect_snapshot_plot(f, label = "hist_grouped_faceted")
diff --git a/man/tinyplot.Rd b/man/tinyplot.Rd
index 3427a5da..a2211f12 100644
--- a/man/tinyplot.Rd
+++ b/man/tinyplot.Rd
@@ -123,9 +123,7 @@ likely the names of existing vectors or columns of data frames. See the
 \code{\link[grDevices]{xy.coords}} for details. If supplied separately, \code{x}
 and \code{y} must be of the same length.}
 
-\item{...}{other graphical parameters (see \code{\link[graphics]{par}}), or
-arguments passed to the relevant plot type (e.g., \code{breaks} for
-\code{type = "histogram"}, or \code{varwidth} for \code{type = "boxplot"}).}
+\item{...}{other graphical parameters (see \code{\link[graphics]{par}}).}
 
 \item{by}{grouping variable(s). The default behaviour is for groups to be
 represented in the form of distinct colours, which will also trigger an
diff --git a/man/type_histogram.Rd b/man/type_histogram.Rd
new file mode 100644
index 00000000..d9c40fe3
--- /dev/null
+++ b/man/type_histogram.Rd
@@ -0,0 +1,30 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/type_histogram.R
+\name{type_histogram}
+\alias{type_histogram}
+\alias{type_hist}
+\title{Histogram type}
+\usage{
+type_histogram(breaks = "Sturges")
+
+type_hist(breaks = "Sturges")
+}
+\arguments{
+\item{breaks}{Passed to \code{\link[graphics]{hist}}. One of:
+\itemize{
+\item a vector giving the breakpoints between histogram cells,
+\item a function to compute the vector of breakpoints,
+\item a single number giving the number of cells for the histogram,
+\item a character string naming an algorithm to compute the number of cells (see ‘Details’ of \code{\link[graphics]{hist}}),
+\item a function to compute the number of cells.
+In the last three cases the number is a suggestion only; as the breakpoints
+will be set to pretty values, the number is limited to 1e6 (with a warning if
+it was larger). If breaks is a function, the x vector is supplied to it as
+the only argument (and the number of breaks is only limited by the amount of
+available memory).
+}}
+}
+\description{
+Type function for histogram plots. \code{type_hist} is an alias for
+\code{type_histogram}.
+}
