We developed a grain-based pore-scale model that tracks capillary-stable positions of fluid–fluid interfaces (menisci) between grains of arbitrary wettability. The model explicitly calculates the stable menisci positions between two-dimensional disks at particular capillary pressures. With changing capillary pressure, the menisci are tracked and conditions for menisci stability in a pore throat (Haines condition) or menisci merging in a pore body (Melrose condition) are elucidated. When a meniscus becomes unstable, a pore-filling event occurs, and an invasion percolation routine is used to find the next stable position of the meniscus (or menisci). We tested the method on networks extracted from two-dimensional porous media consisting of randomly distributed oil-wet and water-wet disks. The model is robust in that it handles both filling mechanisms simultaneously and seamlessly even across changes in capillary pressure from positive to negative values. We compared the results of the two-dimensional model as a function of fractional wettability to experiments in fractionally wet packs. We found good qualitative agreement between the model and the experiments for a water–oil system on both imbibition and drainage.