公元199年,袁绍谋划南下进攻曹操的统治中心许昌。袁绍手下的谋士沮授、田丰认为袁军与公孙瓒战斗了三年,军队已相当疲劳,应先"务农逸民",休养生息,以增强经济与军事力量。他们主张暂时不急于攻打曹操。但是,袁绍的另外两个谋士审配、郭图则力主马上出兵攻曹。袁绍采纳了审配、郭图的意见,挑选精兵十万,战马万匹,陈兵黄河北岸,准备伺机渡河,同曹操决战。
袁绍举兵南下的消息传到许昌,曹操手下的一些部将为袁绍表面的优势所吓倒,认为袁军强不可敌。但曹操很了解袁绍,他对将士们说,袁绍野心虽大,但缺少智谋,表面上气势汹汹,而实际上胆略不足;他疑心重且忌人之能,兵虽多但组织指挥不明而且将帅骄傲、政令不一。因此,战胜他是有把握的。曹操的谋士荀彧也分析了袁绍军队的情况,认为袁军内部不团结,将帅、谋士之间矛盾重重,并非坚不可摧。曹操与荀彧的分析,增强了曹军战胜袁军的信心。曹操经过对敌我双方兵势情况的分析,决定采取以逸待劳、后发制人的战略方针。他将主力调到黄河南岸的官渡(今河南中牟东北),以阻挡袁军从西路进犯;又派臧霸等率兵从徐州入青州,从东方钳制袁绍军队;派于楚屯守黄河南岸的重要渡口延津(今河南延津北),协助扼守白马(今河南滑县东,在黄河南岸)的东群太守刘延,阻滞袁绍的军队渡河和长驱南下进攻。
公元199年十二月,正当曹操布置对袁绍的作战计划时,刘备起兵,占领了曹操征服吕布后占驻的徐州及下邳等地,并派关羽驻守。东海及附近郡县亦多归附刘备。刘军增至数万人,并与袁绍联系打算合力进攻曹操。
曹操为了避免两面作战,打算首先击破刘备。公元200年正月,曹操亲率精兵东击刘备,将刘备击败。当刘、曹作战时,袁绍的谋士田丰建议袁绍袭击曹军的后方,袁绍犹豫不决,没有采纳田丰的建议。因此,曹操顺利地击败了刘备,使刘备只身逃往河北投靠了袁绍,然后及时返回官渡继续抵御袁绍的进攻。
公元200年正月,袁绍发布声讨曹操的檄文。二月,袁绍大军开进黎阳(今河南浚县东北),把这里作为指挥部,企图渡河寻求曹军主力决战。袁绍首先派大将颜良进攻白马的东郡太守刘延,夺取黄河南岸要点,以保障主力渡河。颜良率军渡过黄河,直扑白马与刘延交战,刘延在白马坚守城池,士兵伤亡惨重。这时,曹操的谋士荀攸向曹操献计说:我军兵少,集结在官渡的主力也只有三四万人,要对付袁绍众多的兵力,正面交锋恐怕不易得手,应设法分散袁绍的兵力。他提议曹操引兵先到延津,佯装要渡河攻击袁绍后方,这样,袁绍必然分兵向西;然后曹军再派轻装部队迅速袭击进攻白马的袁军,攻其不备,一定可以击败颜良。曹操采用了荀攸这一声东击西之计,袁绍果然分兵增援延津。曹操见袁绍中计,立即调头率领轻骑,派张辽、关羽为前锋,急趋白马。曹军在距白马十余里时,颜良才发现他们。关羽迅速地迫近颜良军,乘其措手不及,斩颜良于军伍之中。袁军大乱,纷纷溃散。
袁绍围攻白马失败,并丧失了一员大将,十分恼怒。曹操解了白马之围后,便沿黄河向西撤退。袁绍率军渡河追击曹操。这时沮授又谏阻袁绍说:军事上的胜负变化应仔细观察。现在最好的办法还是驻黄河北岸,分兵进攻官渡,若能攻下,大军再过河也不为晚;如果贸然南下,万一失败就有全军覆没的危险。袁绍骄傲自负,根本不听他的劝告。沮授见袁绍如此固执,便推说有病向袁绍要求辞职,袁绍不准,还把他统领的军队交给了郭图指挥。
于是,袁绍领军进至延津以南,派大将文丑与刘备率兵追击曹军。曹操命令士卒解鞍放马,又故意将辎重丢弃道旁,引诱袁军。待袁军逼近争抢辎重时,曹操才命令上马,突然发起攻击,打败了袁军,杀了文丑,顺利地退回官渡。
白马、延津两次战斗是官渡之战的前哨战。袁军虽初战失利,但兵力仍占优势。七月,袁绍进军阳武(今河南中牟北),准备南下进攻许昌。沮授这时又劝袁绍说:我方士兵虽多,但不及曹军勇猛。曹操的粮食、物资不如我们多,速战对曹军有利对我们不利,我们应用旷日持久的办法消耗曹军的实力。但是袁绍仍然不听。袁军于八月逼近官渡,双方在官渡相对峙。
曹军在官渡设防,想寻找时机打击袁军。九月间,曹操向袁军发起一次进攻,但未能取胜。此后,曹操便深沟高垒,固守阵地。袁绍见曹军坚壁不出,便命令士兵在曹军营外堆起土山,砌起高台,用箭射击曹军。曹营士兵来往行走都得用盾牌遮掩身体或匍匐前进。曹操发明了一种抛发石块的车子,发射石块将袁军的壁楼击毁。袁军又挖掘地道以攻曹军,曹操则命令士兵在营内挖掘长沟来截断袁军地道。这样双方之间你来我挡地相持了大约三个月。在相持的过程中,曹操产生了动摇,他觉得自己兵少,粮食不足,士卒极为疲劳;后方也因袁绍派刘备攻击于汝南、颍川之间而不太稳定,这样长期与袁绍周旋相当危险。因此曹操便想退还许昌。他写信给留守许昌的荀彧,征求他的意见。荀彧回信建议曹操坚持下去,他指出:曹军目前处境困难,同样,袁军的力量也几乎用尽,这个时候正是战势即将发生转折的时刻,也是用奇之时,不能失去即将出现的战机,这时谁先退却谁便会陷入被动。曹操听取了他的意见,一方面决心坚持危局,加强防守,命负责供给粮秣的官员想法解决粮草补给问题;另一方面则积极寻求和捕捉战机,想给袁军以有力的打击。
曹操决定以截烧袁军粮食的办法争取主动。他先派人把袁绍将领韩猛督运的数千辆粮车截获烧掉了。不久,袁绍又把一万多车粮食集中在乌巢,派淳于琼等率军守护。沮授鉴于前次粮草被烧,便建议袁绍另派一支部队驻扎在淳于琼的外侧,两军互为犄角,防止曹军抄袭。袁绍觉得此举多余,没有采纳。
袁绍的另一谋士许攸向他献策说:"曹操兵少,集中力量与我军相持,许昌一定空虚,我们可以派一支轻骑日夜兼程袭击许昌。这样可以一举拔取;即使许都拿不下来,也会造成曹操首尾不相顾,来回奔命的局面,进而可以打败他。"袁绍却傲慢地说:"不必,我一定要在此擒住曹操。"他拒绝这一出奇制胜的建议,继续与曹操相持。
恰巧在此时,许攸的家属在邺城犯了法,被留守邺城的审配关押起来了。许攸一怒之下,星夜离开袁营,投降了曹操。曹操热情地迎接他。许攸见曹操重视自己,就向他介绍袁军的情况并献计说:"袁绍的辎重粮草有一万多车在故氏、乌巢,屯军防备不严。如果以精兵袭击,出其不意烧掉他的粮草,不出三天,袁绍必定失败。"粮食是关系到双方胜败的关键,曹操当时只有一个月的军粮,许攸的建议,正符合曹操寻找战机出奇制胜的作战意图。因此,曹操把奇袭乌巢当成是关系全局胜败的重要一着,毫不迟疑地立即实行。他留曹洪、荀攸等守大营,自己亲率步骑五千前往攻打乌巢。
曹军一行一律改穿袁军的服装,用袁军的旗号,夜间从偏僻小道向乌巢进发。途中,他们遇到袁军的盘问,曹军诡称是袁绍为巩固后路调派的援军,骗过了袁军。到达后,他们立即放火烧粮。袁军大乱,袁绍反而认为这是攻下官渡的好机会。他命令高览、张郃等大将领兵去攻打曹军大营。张郃指出这样做很危险,曹操领精兵攻打乌巢,如果乌巢有失,事情就不好办了。张郃主张先救乌巢。但袁绍手下的谋士郭图迎合袁绍的意图,坚决主张攻打曹营,他认为攻打曹营,曹操必定引兵回救,这样,乌巢之围就会自解。于是袁绍只派少量军队救援乌巢,而以主力攻关渡曹营,曹营十分坚固,一时攻打不下。
曹操得知袁军进攻自己大本营的消息后,并没有马上回救,而是奋力击溃淳于琼的军队,决心将袁绍在乌巢积存的粮食全部烧掉。这时,袁绍增援的骑兵迫近乌巢,曹操左右的人请求他分兵阻挡。曹操没有分兵,说:"等敌人到了背后再报告!"这样,曹军士卒都与敌军殊死决战,最后大破淳于琼军,杀淳于琼并将其全部粮草烧毁。乌巢粮草被烧光的消息传到袁军前线,袁军军心动摇。原来反对张郃用重兵救援乌巢主张的郭图等害怕袁绍追究自己的责任,就在袁绍面前说张郃为袁军失败而高兴。张郃遭到了中伤,既气愤又害怕,便与高览一起焚毁了攻战器具,投降了曹操。这使得袁军军心更加不稳,军队不战自乱。这时,曹操趁机率军全面发起攻击,迅速消灭了袁兵七万多人,袁绍仓皇退回了河北。官渡之战以曹胜袁败而结束。官渡之战正是《势篇》所说"凡战者,以正合,以奇胜"的最佳实例,曹操焚烧袁军粮草,抓住了于己军有利的"势",并且"择人而任势",取得了最后的胜利。官渡之战奠定了曹操北方霸主的地位。