整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

简要地教你使用HTML 5.2对话框

简要地教你使用HTML 5.2对话框

TML对话框已经停留了一段时间,但是直到最近,它还不是W3C推荐规范的一部分。既然主流浏览器已经开始支持对话元素,我们很可能会看到它被广泛使用。本文简要介绍了我们如何使用对话框,为什么需要新的元素以及如何使用它。

什么是对话框?

对话框是一种可用于多种方式的设计模式,包括但不限于:显示重要信息,请求用户选择或扩展现有内容。虽然对话可以以不同的方式进行,但是最常用的是模态,与叠加层中的其他内容隔离。

为什么需要对话框元素?

直到新元素发布,要实现一个对话框到一个网站,你将不得不从头开始编写或使用外部库 - 这种组件没有标准的语法或默认样式。缺乏标准意味着浏览器和屏幕阅读器等辅助技术默认情况下无法区分对话框相关内容和其他页面内容。

为了解决可访问性问题,开发人员必须使用aria属性(如role=“dialog”)来描述对话框中的内容。正确管理键盘焦点对于使用对话框的可访问性也很重要,例如,对话框中必须至少有一个可调焦的控件。

一些伟大的库被创建,使开发者更容易实现可访问的对话框,比如Edenspiekermann的A11y Dialog。除了这样的库之外,像Bootstrap和Foundation这样的CSS框架也使得它们内置的模式/对话框变得可用。

尽管今天这些库和框架仍然是相关的和有用的,但是具有用于对话的本地HTML元素确保了这样的经常使用的设计模式对于每个人都是很好的语法,标准和可访问性。另外,在浏览器中内置对话逻辑可以节省那些宝贵的代码字节!

使用对话框元素

现在我们明白为什么需要这个了,我们来看看我如何使用对话框元素。

HTML代码

对话框元素的标记就像在<dialog>标签中包装一些内容一样简单。为了使对话框起作用,我们需要一个按钮来打开它,还有一个按钮可以关闭或者撤销它。

要使对话框默认打开,可以添加一个打开的属性。

如果您的对话框包含一个表单,则表单元素的方法属性应设置为对话框。

JavaScript代码

没有JavaScript,对话元素将不会交互。我们可以将上面的HTML例子中的按钮和对话框元素连接到一些点击事件监听器。

就是这样,我们有一个可以正常运行本地化的对话框!

CSS代码

对话框元素的默认样式不会适合每个人的口味......比较幸运的是,我们可以用CSS来设计样式。

还有一个backdrop可以帮助我们选择不同的背景

完整demo演示如下:

支持

早在2014年,Chrome和Opera就开始支持对话元素,最近又推出了Chrome Android和三星浏览器。它也支持Firefox,但必须通过about:config启用。尽管有几个主要的浏览器不支持dialog,但有一个很好的polyfill可用。

窗这类组件已经十分常见,那么,这类组件应该怎么设计?这篇文章里,作者针对弹窗的设计方式做了详细拆解,一起来看看,或许会对想了解C端界面组件的同学有所帮助。

一、组件介绍

弹窗是一种瞬态的交互式视图,它会在“合适”的时间弹出到页面的最顶层,并借由用户的一次点击完成关闭。

在我们习惯的语境中,弹窗仅指模态弹窗,故这里不讨论那些看上去也是弹出式却非模态弹窗,那些控件均有自己专门的分类,例如 Toast(吐司提示)。

这里需要专门解释一下模态(Modal),模态是指一种会打断用户原本的任务流,并强制用户完成当前交互的控件场景。

通常情况下会出现一层遮罩,将原页面和需要交互的控件隔离开来,在用户完成交互或点击关闭该控件之前,无法在原来的页面上继续流程。例如典型的模态控件有:警告、抽屉、活动视图、动作表单等等。

在过去的交互实践中,模态是一种强制打断用户的场景,所以除非是优先级非常高的或紧急的情况,否则都会建议谨慎使用模态。不过这种谨慎的态度在如今的设计实践中已经渐渐出现了一些变化。

二、使用场景

弹窗有两种主要的使用场景。

1. 警告 Alert / 对话框 Dialog

两者是同一功能的控件,在 iOS 中称为 Alert,也就是警告,在 Android 中被称为 Dialog,也就是对话框。这是模态弹窗最传统的用法,它通常是对系统层优先级最高的、最实时需要用户做判断或操作的事件进行的一种弹出式控件。在用户完成该事件的处理之前,无法与别的控件进行交互。

在之后的行文中,我都会以警告来统称警告和对话框。

2. 运营弹窗

这就是我之前说的,随着新时代互联网的深入发展,运营需求开始覆盖并刷新系统各个控件原本的设计意图,运营弹窗就此应运而生。但运营弹窗并非只能是广告、抽奖、优惠券之类的活动内容,也可以是 App 内测邀请、升级提醒、请求开启通知权限等偏功能的运营提示。

相对来说运营弹窗会比普通的警告承载更多的设计元素,会大幅度强化视觉的比重,但在交互上是跟警告没有太多区别的——模态加简单的交互依然是运营弹窗主要的交互特征。

三、设计要点

1. 弹窗的位置

在普遍的概念中模态弹窗好像都是出现在屏幕正中心,但其实不是这样,模态弹窗还可以出现屏幕的底部,这么做的很少见,但的确有,例如抖音的青少年模式弹窗(这是弹窗,不是活动视图,需要加以区分)。

2. 警告的三段式主体

在大多数情况下,警告弹窗都包含三部分主体,从上至下分别是:标题区、描述区和交互区。这三部分是警告弹窗的基本骨架,想要做更深一步的精细设计,也是在这三个部分的基础之上。

1)标题的布局

在设计实践中,标题的对齐可以居中或者居左。一般来说,在 iOS 中警告的标题默认居中,在 Android 中对话框的标题默认居左。

2)描述的布局

描述的布局大体上应与标题的布局保持一致,标题是如何对齐的,描述就如何对齐。

3)交互按钮的布局

交互按钮如果少于或等于两个,那么优先使用水平排版,在此情况下还可以进一步选择均分或者偏置,由于拇指的活动范围有限,一般偏置在右侧。

另一种垂直排版则适合任何数量的按钮——尽管 iOS 规范要求交互按钮的数量不超过三个,但实际情况却依然需要具体问题具体分析,存在更多按钮也是可能的。

4)交互按钮的权重

通常我们还能看到 App 设计者会对不同的交互操作给予不同的倾向,这种倾向有时是功能需求,有时是运营需要,会让倾向的按钮更突出,会让反倾向的按钮更不易察觉(甚至置灰),会让危险的按钮呈现红色。

5)额外内容

除了以上标准的三段式区域之外,警告弹窗内还可以加入其它一些额外的内容。描述区域可以依据情况增加额外的控件或设计元素,例如最常见的对话框,可以允许用户输入文本后再进行下一步操作;标题区域之上也可以增加一个图标区,图标可以更直观提示该警告事件需求的操作、完成状态或进程。

3. 警告的文案设计

在警告弹窗的设计中,因为它的强功能性,这三段的文案要求要大于设计要求,尽管文案几乎不归我们设计师管,但是我在这里还是提一下这几个部分的文案要求。

标题——尽可能简练得总结当前所处的情况;如需额外操作,询问用户操作意见。

如果描述本身非常的长,那么就一定要加标题去凝练当前的事件,包括目前遇到的情况,以及可能的解决方案并询问用户的意见。

描述——尽可能用直接、人性化的口吻说出目前遇到的问题。

如果 App 是面向大众用户的,尽量避免用理工科思维写出一些很绕且生涩的描述,尤其是如果中间还有程序语言那会更糟。这一点 windows 做的就非常不足,充满了理工科的自说自话的气息,也不管用户到底看不看得懂。

按钮——给出对结果的描述,避免要求语义逻辑判断。

按钮的文案最好是对结果的直接描述,按钮上说的是什么,结果就会是什么,而不要让用户做语文题,否定之否定等于肯定这样的情况避免出现——除非是故意的。例如“是否删除XXXX”,正确的按钮文案应当是“删除”和“保留”,而非“是”和“否”。

4. 运营弹窗的三段式主体

尽管运营弹窗的布局可能眼花缭乱,但是它依然大致符合模态弹窗的三段式:标题、描述和交互按钮。只不过运营弹窗的各个部分会辅以视觉元素表达。

此外,最重要的一点是,运营弹窗一定不能缺少「关闭」按钮,虽然这个按钮通常会浮在弹窗主体之外,是大是小全看想不想让用户轻易点到,但它不可或缺,否则用户不知道如何退出这个弹窗。

5. 运营弹窗视觉元素的类型

随着各类型 App 运营要求的逐渐提升,运营弹窗中视觉元素的运用也越发频繁且有往愈加浮夸的方向发展的苗头。可以在运营弹窗中使用的视觉元素大致有以下几种:

1)图标

最基础的视觉元素,还是以常用的矩形为基底,但会辅以契合内容的图标,其形式更加类似于警告。

2)插画

现在最常见的花哨形式,插画风格的多变性决定了它会在运营内容中大放异彩,甚至可以抛弃矩形边界,完全以插画内容为主体。

3)3D / 仿3D

随着 3D 更多地进入 UI 领域,运营弹窗也逐渐开始使用 3D 元素,或者仿 3D 的元素。

4)图片/视频

图片和视频多用在品牌营销的广告中,不管是人还是物,都可以直接在弹窗中置入品牌的广告物料图或视频。

四、样式拓展

这里收集了一些弹窗的案例,也可以作为设计时的参考:

作者:酸梅干超人;公众号:超人的电话亭(ID:Superman_Call)

本文由 @超人的电话亭 原创发布于人人都是产品经理,未经许可,禁止转载。

题图来自Unsplash ,基于 CC0 协议

该文观点仅代表作者本人,人人都是产品经理平台仅提供信息存储空间服务。



软件开发中,很多地方需要用到与用户消息提醒,用form绘制一个自己消息框。

首先在界面上绘制两个按钮,在之前文章有教程绘制一个button方法,也可以直接使用系统。

私有属性

        #region 私有属性

        private string message;
        private MesBoxIcon mesIcon;

        #endregion

公有属性

        #region 公有属性

        public MesBoxIcon MesIcon
        {
            get=> mesIcon;
            set
            {
                mesIcon=value;
                this.Invalidate();
                if (value==MesBoxIcon.Info)
                {
                    wenImageButton1.Visible=false;
                }
            }
        }

        public string Message
        {
            get=> message;
            set
            {
                message=value;

                Graphics g=this.CreateGraphics();
                SizeF sizef=g.MeasureString(value, this.Font);

                int width=(int) sizef.Width + this.FrameWidth * 2 + 80;
                int height=this.TitleHeight + this.FrameWidth + panel1.Height;

                this.Size=new Size(this.Width < width ? width : this.Width, this.Height < height ? height : this.Height);

                this.Invalidate();
            }
        }

        #endregion

MesBoxIcon 消息类型选择


找到与自己需要绘制的图档

        public enum MesBoxIcon
        {
            Asterisk,
            Error,
            Info,
            Warning,
        }

采用GDI绘制消息框

protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Rectangle rec=new Rectangle(this.FrameWidth, this.TitleHeight, this.Width - this.FrameWidth * 2, this.Height - this.TitleHeight - this.FrameWidth - panel1.Height);

            Rectangle recStr=new Rectangle(rec.X + 70, rec.Y, rec.Width - 70, rec.Height);

            Rectangle recIco=new Rectangle(rec.X + 5, rec.Y + (rec.Height - 60) / 2, 60, 60);

            Graphics g=e.Graphics;
            g.DrawString(Message, Font, new SolidBrush(this.ForeColor), recStr, WenSkin.Controls.ControlHelper.StringConters);

            switch (MesIcon)
            {
                case MesBoxIcon.Asterisk:
                    g.DrawImage(Properties.Resources.Asterisk, recIco);
                    break;
                case MesBoxIcon.Error:
                    g.DrawImage(Properties.Resources.error, recIco);
                    break;
                case MesBoxIcon.Info:
                    g.DrawImage(Properties.Resources.Info, recIco);
                    break;
                case MesBoxIcon.Warning:
                    g.DrawImage(Properties.Resources.Warning, recIco);
                    break;
                default:
                    break;
            }
        }


两个按钮点击事件


        private void wenImageButton2_Click(object sender, EventArgs e)
        {
            this.DialogResult=DialogResult.OK;
        }

        private void wenImageButton1_Click(object sender, EventArgs e)
        {
            this.DialogResult=DialogResult.Cancel;
        }


可以根据自己需求更改。

多个构造函数示例


        public MesBox()
        {
            InitializeComponent();
            this.SizeChanged +=(s, e)=>
            {
                if (wenImageButton1 !=null)
                    wenImageButton1.Width=(this.Width - this.FrameWidth * 2) / 2;
            };
            Text="消息";
            mesIcon=MesBoxIcon.Info;
            this.StartPosition=FormStartPosition.CenterScreen;
        }

        public MesBox(string text) : this()
        {
            Message=text;
        }
        public MesBox(string text,MesBoxIcon mesBoxIcon) : this(text)
        {
            MesIcon=mesBoxIcon;
            switch (MesIcon)
            {
                case MesBoxIcon.Asterisk:
                    Text="提醒";
                    break;
                case MesBoxIcon.Error:
                    Text="错误";
                    break;
                case MesBoxIcon.Info:
                    Text="消息";
                    break;
                case MesBoxIcon.Warning:
                    Text="警告";
                    break;
                default:
                    break;
            }
        }
        public MesBox(string text,string caption, MesBoxIcon mesBoxIcon) : this(text)
        {
            Text=caption;
        }

至此,一个自主弹窗绘制完成

接下来调用

            var m=new MesBox(text, MesBox.MesBoxIcon.Asterisk).ShowDialog();
            if (m==DialogResult.OK)
                 true;
            else
                 false;

一行代码即可,是不是很方便。


关注文林软控,带你一起C# 美化.NET 控件。