In this chapter, we’ll explore the various formatting options available for BarMark in Swift Charts. We will learn how to adjust color, size, corner radius, opacity, and more—giving us full control over the look and feel of our charts. These formatting tools not only enhance aesthetics but also help convey meaning more effectively through visual cues.

Coloring the Bars

We can use the foregroundStyle modifier to change the color of bars. Since the foregroundStyle modifier accepts a ShapeStyle type parameter, we can use gradient colors instead of solid colors for our bar charts.

import Charts

struct Workout: Identifiable {
    var id = UUID()
    var day: String
    var minutes: Double
}

extension Workout {
    static let workouts: [Workout] = [
        Workout(day: "Mon", minutes: 32),
        Workout(day: "Tue", minutes: 45),
        Workout(day: "Wed", minutes: 56),
        Workout(day: "Thu", minutes: 15),
        Workout(day: "Fri", minutes: 65),
        Workout(day: "Sat", minutes: 8),
        Workout(day: "Sun", minutes: 10),
    ]
}

struct ChartsExampleView: View {
    var body: some View {
        VStack {
            Text("DevTechie.com")
                .font(.largeTitle)
            Chart(Workout.workouts) { workout in
                BarMark(
                    x: .value("Day", workout.day),
                    y: .value("Min", workout.minutes)
                )
                .foregroundStyle(.indigo.gradient) // bar color
            }
            .frame(height: 200)
        }
    }
}

In this case, all of our bars are colored with the same indigo color, but we can customize that by fetching the color value from the model. To do this, we’ll add a color property inside the Workout model and update the sample data to provide a color for each of the sample entries.

struct Workout: Identifiable {
  var id = UUID()
  var day: String
  var minutes: Double
  var color: Color
}

extension Workout {
  static let workouts: [Workout] = [
    Workout(day: "Mon", minutes: 32, color: .orange),
    Workout(day: "Tue", minutes: 45, color: .red),
    Workout(day: "Wed", minutes: 56, color: .pink),
    Workout(day: "Thu", minutes: 15, color: .mint),
    Workout(day: "Fri", minutes: 65, color: .cyan),
    Workout(day: "Sat", minutes: 8, color: .indigo),
    Workout(day: "Sun", minutes: 10, color: .blue),
  ]
}

Once we’ve added the color property inside the model, we’re ready to use it within the chart.

struct ChartsExampleView: View {
    var body: some View {
        VStack {
            Text("DevTechie.com")
                .font(.largeTitle)
            Chart(Workout.workouts) { workout in
                BarMark(
                    x: .value("Day", workout.day),
                    y: .value("Min", workout.minutes)
                )
                .foregroundStyle(workout.color.gradient)
            }
            .frame(height: 200)
        }
    }
}

#Preview {
  ChartsExampleView()
}

Let’s use the mesh gradients(introduced in WWDC24) for our example.

Creating a mesh gradient involves specifying the width and height of the gradient, positions for each color, and the colors to display. While positions can be specified using SIMD2 for performance, we can also use arrays of X/Y unit positions.

For example, here’s how to create a 2x2 box with four colors:

MeshGradient(width: 2, height: 2, points: [
  [0, 0], [1, 0], [0, 1], [1, 1]
], colors: [workout.color, .purple, .teal, .yellow])

Update the foregroundStyle modifier to include the mesh gradient.

.foregroundStyle(MeshGradient(width: 2, height: 2, points: [
  [0, 0], [1, 0], [0, 1], [1, 1]
], colors: [workout.color, .purple, .teal, .yellow]))

Code should look like this

struct ChartsExampleView: View {
    var body: some View {
        VStack {
            Text("DevTechie.com")
                .font(.largeTitle)
            Chart(Workout.workouts) { workout in
                BarMark(
                    x: .value("Day", workout.day),
                    y: .value("Min", workout.minutes)
                )
                .foregroundStyle(MeshGradient(width: 2, height: 2, points: [
                    [0, 0], [1, 0], [0, 1], [1, 1]
                ], colors: [workout.color, .purple, .teal, .yellow]))
            }
            .frame(height: 200)
        }
    }
}

#Preview {
    ChartsExampleView()
}

The foregroundStyle modifier has another overloaded function that accepts a PlottableValue as a parameter. The Charts framework automatically selects colors for the bars, making them easily distinguishable.

struct ChartsExampleView: View {
    var body: some View {
        VStack {
            Text("DevTechie.com")
                .font(.largeTitle)
            Chart(Workout.workouts) { workout in
                BarMark(
                    x: .value("Day", workout.day),
                    y: .value("Min", workout.minutes)
                )
                .foregroundStyle(by: .value("Day", workout.day))
            }
            .frame(height: 200)
        }
    }
}

If you look closely, you’ll notice a new Legend view has been added to the screen. When you first create a chart with different foreground styles, the chart legends automatically appear. These legends display the names and colors of each data series. The legend text is based on the nominal values of the chart.

ClipShape

The clipShape modifier in Swift Charts can be used to mask a BarMark to a specific shape, effectively clipping the bar to that shape. This allows us to create visually interesting and customized bar charts with non-rectangular shapes.

Let’s try the clipShape modifier to transform BarMarks into rounded rectangle shapes.

import Charts
import SwiftUI

struct Workout: Identifiable {
    var id = UUID()
    var day: String
    var minutes: Double
    var color: Color
}

extension Workout {
    static let workouts: [Workout] = [
        Workout(day: "Mon", minutes: 32, color: .orange),
        Workout(day: "Tue", minutes: 45, color: .red),
        Workout(day: "Wed", minutes: 56, color: .pink),
        Workout(day: "Thu", minutes: 15, color: .mint),
        Workout(day: "Fri", minutes: 65, color: .cyan),
        Workout(day: "Sat", minutes: 8, color: .indigo),
        Workout(day: "Sun", minutes: 10, color: .blue),
    ]
}

struct ChartsExampleView: View {
    var body: some View {
        VStack {
            Text("DevTechie.com")
                .font(.largeTitle)
            Chart(Workout.workouts) { workout in
                BarMark(
                    x: .value("Day", workout.day),
                    y: .value("Min", workout.minutes)
                )
                .foregroundStyle(by: .value("Day", workout.day))
                .clipShape(.rect(cornerRadius: 10)) // rounded rect
            }
            .frame(height: 200)
        }
    }
}

#Preview {
    ChartsExampleView()
}


Let’s try out other shapes as well.

Capsule:

struct ChartsExampleView: View {
  var body: some View {
    VStack {
      Text("DevTechie.com")
        .font(.largeTitle)
      Chart(Workout.workouts) { workout in
        BarMark(
          x: .value("Day", workout.day),
          y: .value("Min", workout.minutes)
        )
        .foregroundStyle(by: .value("Day", workout.day))
        .clipShape(.capsule)
      }
      .frame(height: 200)
    }
  }
}

Ellipse:

struct ChartsExampleView: View {
  var body: some View {
    VStack {
      Text("DevTechie.com")
        .font(.largeTitle)
      Chart(Workout.workouts) { workout in
        BarMark(
          x: .value("Day", workout.day),
          y: .value("Min", workout.minutes)
        )
        .foregroundStyle(by: .value("Day", workout.day))
        .clipShape(.ellipse)
      }
      .frame(height: 200)
    }
  }
}

Circle:

struct ChartsExampleView: View {
  var body: some View {
    VStack {
      Text("DevTechie.com")
        .font(.largeTitle)
      Chart(Workout.workouts) { workout in
        BarMark(
          x: .value("Day", workout.day),
          y: .value("Min", workout.minutes)
        )
        .foregroundStyle(by: .value("Day", workout.day))
        .clipShape(.circle)
      }
      .frame(height: 200)
    }
  }
}

Conclusion

Swift Charts gives us an impressive degree of control over the visual styling of BarMark, allowing us to move far beyond basic rectangular bars. In this chapter, we explored how to enhance the appearance of bar charts by customizing color with foregroundStyle, applying mesh gradients for richer visuals, and experimenting with shape clipping to create unique chart designs. Whether we are building charts for fitness data, financial dashboards, or habit tracking, these formatting tools allow us to present information in a way that’s both visually appealing and contextually meaningful.