You can treat geom_ribbon
the same as any other geom—create multiple based on some aspect of the data and map values to aesthetics. So the y-min & y-max arguments can be handled like you would color, fill, size, etc. inside aes
, including different values of those offsets. To illustrate, I've just added a column that gives those offsets, which are then used to determine the width of the ribbons. You can set the color of the line and the fill of the ribbon to match, as I did here, or use different sets of colors.
library(dplyr)
library(ggplot2)
data(mtcars)
var1 <- mtcars$mpg
var2 <- mtcars$mpg + 5
df <- reshape::melt(cbind(var1, var2)) %>%
mutate(gap = ifelse(X2 == "var1", 1, 2))
ggplot(df, aes(x = X1, y = value, color = X2)) +
geom_line() +
geom_ribbon(aes(ymin = value - gap, ymax = value + gap, fill = X2), alpha = 0.3, color = NA) +
scale_fill_manual(values = c("skyblue", "coral"), aesthetics = c("color", "fill"))

Since this question is 4 years old, I'll point out also that giving the aesthetics
argument in the scale is a shortcut added recently to set the same palette to multiple encodings at once (in this case, both color and fill); I rarely actually use it, but it fit the problem here.