For example, consider the -> function type constructor. It has two parameters, the input type and the output type. Examples of function types are int->int and bool->bool.
The first parameter of the -> constructor (the type of the input) is contravariant while the second (the type of the output) is covariant.
For another example, consider the type of a generic immutable list, List<T>. The T type parameter of the List constructor is covariant.
A function has variance because the types of its inputs or outputs are in a hierarchy.
An object type system (or I suppose even a functor system?) with generics might leverage variance to make sure that the behavior of its own methods is consistent with the Substitution Principle (LSP).
And many people will tldr this into variance being the tool to give you a type system that is LSP compatible. But it’s all about the operations, consuming and emitting types.