# Plot: Rects overflow when domain is explicitly set on binned axis

**URL:** <https://talk.observablehq.com/t/plot-rects-overflow-when-domain-is-explicitly-set-on-binned-axis/6223>\
**Category:** Help\
**Created:** [February 14, 2022, 5:13pm UTC](https://talk.observablehq.com/t/plot-rects-overflow-when-domain-is-explicitly-set-on-binned-axis/6223 "2022-02-14T17:13:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jocsch](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jocsch/32/6147_2.png) [@jocsch](https://talk.observablehq.com/u/jocsch)\
**Post date:** [February 14, 2022, 5:13pm UTC](https://talk.observablehq.com/t/plot-rects-overflow-when-domain-is-explicitly-set-on-binned-axis/6223/1 "2022-02-14T17:13:05Z")

</div>

I have the following plot where the rect “overbleeds” the y axis:

```auto
 Plot.plot({
  width: width,
  y: {
    grid: true,
    label: "↑ count"
  },
  x: { domain:[d3.min(data, d => d.date), d3.max(data, d=>d.date)]},
  marks: [
    Plot.rectY(data, Plot.binX({y: "count"}, {x: k => k.date, thresholds: range, fill: "#444791"})),
    Plot.ruleY([0])
  ]
})

```

[working example](https://observablehq.com/d/3c81b3fa88331148)

Using `inset` on the axis cures the symptom, but only if another bin-range is chosen and the rects changes their width.  
This only happens when the domain is explicitly set with the `min` and `max` value.

What can I do to get the plot properly rendered?

---

<div class="post-metadata">

**Author:** ![Fil](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/fil/32/207_2.png) [@Fil](https://talk.observablehq.com/u/Fil)\
**Post date:** [February 14, 2022, 6:07pm UTC](https://talk.observablehq.com/t/plot-rects-overflow-when-domain-is-explicitly-set-on-binned-axis/6223/2 "2022-02-14T18:07:16Z")

</div>

There are two ways you could do this:

- the first is to set the min and max to the first day of the first month, and the last day of the last month, rather than on the first and the last days of the dataset.

```auto
x: { domain:[d3.utcMonth.floor(d3.min(data, d => d.date)), d3.utcMonth.ceil(d3.max(data, d=>d.date))]},

```

- the second will be to use the forthcoming `{clip: true}` option in the bar mark; it’s available in the development version, and hopefully should be deployed on observable later this week.

The result of both options are shown below:

 ![Capture d’écran 2022-02-14 à 19.05.44](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/3/33fc9d29670e1541dcbb6a5a70eeaaa3cf2491c4.png)

(Note that in the second case the clipped bars are difficult to interpret, so I’d recommend the first approach.)

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [February 14, 2022, 6:41pm UTC](https://talk.observablehq.com/t/plot-rects-overflow-when-domain-is-explicitly-set-on-binned-axis/6223/3 "2022-02-14T18:41:28Z")

</div>

> [@jocsch](#):
>
> This only happens when the domain is explicitly set with the `min` and `max` value.

So don’t set it? Why do you want/feel the need to set the domain explicitly?

I’ll also add that you can add `nice: range` to nice your domain to match the thresholds you are using for bins. This allows you to set the domain semi-explicitly, while still guaranteeing that it aligns with bin thresholds. That would look like this:

 ![untitled-247](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/9/979a7c098c02385b669bda054ed5d0ff21370862.png)

```js
Plot.plot({
  width,
  x: {
    domain: d3.extent(data, (d) => d.date), // note: redundant
    nice: range
  },
  y: {
    grid: true
  },
  marks: [
    Plot.rectY(
      data,
      Plot.binX(
        { y: "count" },
        { x: "date", thresholds: range, fill: "#444791" }
      )
    ),
    Plot.ruleY([0])
  ]
})

```

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [February 14, 2022, 6:47pm UTC](https://talk.observablehq.com/t/plot-rects-overflow-when-domain-is-explicitly-set-on-binned-axis/6223/4 "2022-02-14T18:47:19Z")

</div>

Oh, one more option is that you can explicitly opt-out of extending the first and last bin to cover a complete interval by computing the thresholds yourself:

 ![untitled-248](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/a/ad3e4afda8a9a246417ab799ff7f438f6d79dcac.png)

```nohighlight
Plot.plot({
  width,
  y: {
    grid: true
  },
  marks: [
    Plot.rectY(
      data,
      Plot.binX(
        { y: "count" },
        {
          x: "date",
          thresholds: (_, lo, hi) => range.range(lo, hi),
          fill: "#444791"
        }
      )
    ),
    Plot.ruleY([0])
  ]
})

```

(I removed explicitly computing the x-domain here because it’s redundant.)

---

<div class="post-metadata">

**Author:** ![jocsch](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jocsch/32/6147_2.png) [@jocsch](https://talk.observablehq.com/u/jocsch)\
**Post date:** [February 14, 2022, 6:58pm UTC](https://talk.observablehq.com/t/plot-rects-overflow-when-domain-is-explicitly-set-on-binned-axis/6223/5 "2022-02-14T18:58:52Z")

</div>

> [@mbostock](#):
>
> So don’t set it? Why do you want/feel the need to set the domain explicitly?

Makes no sense in this example I agree. I mistakenly tried to simplify the example.  
In the real use case I want to show a fixed range in the plot. Like the last half year independent from the data that is available. So the starting point is kind of fixed.

I guess I could still make `floor` work in this case but `nice:range` seems to do what I want, right of the box.

Many thanks! I am blown away by that quick response and the manifold options you provide.
