HTML表格中的垂直(旋转)文本

120

有没有一种(便携的)方法可以将HTML表格单元格中的文本旋转90°?

(我有一个包含许多列和大量标题文本的表格,因此我想将其垂直编写以节省空间。)


3
附加答案在此处:https://dev59.com/uW855IYBdhLWcg3wlFSP - Erel Segal-Halevi
可能是垂直文本方向的重复问题。 - user177800
11个回答

105

.box_rotate {
     -moz-transform: rotate(7.5deg);  /* FF3.5+ */
       -o-transform: rotate(7.5deg);  /* Opera 10.5 */
  -webkit-transform: rotate(7.5deg);  /* Saf3.1+, Chrome */
             filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083);  /* IE6,IE7 */
         -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; /* IE8 */
    }
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae porta lectus. Suspendisse dolor mauris, scelerisque ut diam vitae, dictum ultricies est. Cras sit amet erat porttitor arcu lacinia ultricies. Morbi sodales, nisl vitae imperdiet consequat, purus nunc maximus nulla, et pharetra dolor ex non dolor.</div>
<div class="box_rotate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae porta lectus. Suspendisse dolor mauris, scelerisque ut diam vitae, dictum ultricies est. Cras sit amet erat porttitor arcu lacinia ultricies. Morbi sodales, nisl vitae imperdiet consequat, purus nunc maximus nulla, et pharetra dolor ex non dolor.</div>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae porta lectus. Suspendisse dolor mauris, scelerisque ut diam vitae, dictum ultricies est. Cras sit amet erat porttitor arcu lacinia ultricies. Morbi sodales, nisl vitae imperdiet consequat, purus nunc maximus nulla, et pharetra dolor ex non dolor.</div>

取自 http://css3please.com/

截至2017年,上述网站已简化规则集,删除旧版Internet Explorer过滤器,并更多地依赖现在标准的transform属性

.box_rotate {
  -webkit-transform: rotate(7.5deg);  /* Chrome, Opera 15+, Safari 3.1+ */
      -ms-transform: rotate(7.5deg);  /* IE 9 */
          transform: rotate(7.5deg);  /* Firefox 16+, IE 10+, Opera */
}
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae porta lectus. Suspendisse dolor mauris, scelerisque ut diam vitae, dictum ultricies est. Cras sit amet erat porttitor arcu lacinia ultricies. Morbi sodales, nisl vitae imperdiet consequat, purus nunc maximus nulla, et pharetra dolor ex non dolor.</div>
<div class="box_rotate">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae porta lectus. Suspendisse dolor mauris, scelerisque ut diam vitae, dictum ultricies est. Cras sit amet erat porttitor arcu lacinia ultricies. Morbi sodales, nisl vitae imperdiet consequat, purus nunc maximus nulla, et pharetra dolor ex non dolor.</div>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae porta lectus. Suspendisse dolor mauris, scelerisque ut diam vitae, dictum ultricies est. Cras sit amet erat porttitor arcu lacinia ultricies. Morbi sodales, nisl vitae imperdiet consequat, purus nunc maximus nulla, et pharetra dolor ex non dolor.</div>


9
有一个问题,表格标题的th列在需要旋转时宽度不会增加,所以看起来有些模糊(在Firefox中尝试过):( - xaralis
3
是的,在Firefox(不确定其他浏览器)中,<tr> 要么旋转而列的其余部分不会调整,要么可以在 <tr> 中放置一个 <div> 并尝试将 <tr> 的位置设置为相对位置,将包含的 <div> 设置为绝对位置并使用 -moz-transform-origin: 0 50% 来改正其位置。为了获取正确的宽度和高度,您可能需要使用 jQuery 或其他工具将 <tr> 的宽度和高度分别设置为 <div> 的高度和宽度。 - Adrian Garner
对于IE10,请使用-ms-transform: rotate(7.5deg); - David Sykes
2
只有在您拥有正方形单元格时才有效,因此不会节省任何水平空间。 - 99 Problems - Syntax ain't one
1
这仅适用于“正方形”的单元格,否则旋转后,高度和宽度也会随元素一起旋转,从而破坏外观,并且元素文本重叠在其他位置。 - Rajshekar Reddy
显示剩余2条评论

35

替代方案?

除了旋转文本,将其“从上到下”书写是否可行?

像这样:

S  
O  
M  
E  

T  
E  
X  
T  

我认为这会更容易-您可以拆分文本字符串并在每个字符后插入一个换行符。
可以通过浏览器中的JavaScript来完成此操作,如下所示:
"SOME TEXT".split("").join("\n")

或者您可以在服务器端进行操作,这样它就不会依赖于客户端的JS功能。(我假设这就是您所说的“可移植性”?)

此外,用户不必将头歪向一边才能阅读。

更新

这个帖子 是关于使用jQuery实现这个功能的。


1
有研究表明,这种布局不如左/右旋转布局易读。 - Édouard Lopez

14

在原回答和我的先前回答中有一句引语,位于分号附近。糟了,非常糟糕!下面的代码已经正确设置并且有效。必须在IE中使用浮动才能应用过滤器。

<div style="
    float: left;
    position: relative;
    -moz-transform: rotate(270deg);  /* FF3.5+ */
    -o-transform: rotate(270deg);  /* Opera 10.5 */
    -webkit-transform: rotate(270deg);  /* Saf3.1+, Chrome */
    filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);  /* IE6,IE7 */
    -ms-filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); /* IE8 */
"
>数量和价值;

5
+1是为了指出在IE中使此工作需要使用浮点数的必要性。 - RET

4

我第一次为社区做出贡献,例如旋转简单文本和表头,只使用HTML和CSS。

enter image description here

HTML

<div class="rotate">text</div>

CSS

.rotate {
  display:inline-block;
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  -webkit-transform: rotate(270deg);
  -ms-transform: rotate(270deg);
  transform: rotate(270deg);
}

这里是一个在 jsfiddle 中的例子


目前建议使用代码片段而非 jsfiddle。代码片段是更好的选择。 - matsjoyce
如果我理解正确的话,这些是最新的CSS规则,与Álvaro G. Vicario的解决方案相比? - Florian Jenn
@matsjoyce的代码片段有很多漏洞,而且还会中途崩溃,导致工作丢失。 - Rajshekar Reddy
1
这个答案仅适用于正方形单元格... 对于矩形单元格会出现错误 http://jsfiddle.net/a2uxgm44/156/ - Rajshekar Reddy

4

经过两个多小时的尝试,我可以确定迄今为止提到的所有方法都无法跨浏览器或者甚至IE浏览器的不同版本起作用...

例如(最受欢迎的答案):

 filter:  progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083);  /* IE6,IE7 */
     -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; /* IE8 */

在IE9中,滤镜和-ms-filter都要旋转两次...

所有其他提到的方法也不起作用,至少如果您不必设置表头单元格(带背景颜色)的固定高度/宽度,那么它应自动调整为最高元素的大小。

因此,对于Nathan Long提出的服务器端图像生成方法,这确实是唯一通用的方法,以下是我的VB.NET代码示例,用于通用处理程序(*.ashx):

Imports System.Web
Imports System.Web.Services


Public Class GenerateImage
    Implements System.Web.IHttpHandler


    Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        'context.Response.ContentType = "text/plain"
        'context.Response.Write("Hello World!")
        context.Response.ContentType = "image/png"

        Dim strText As String = context.Request.QueryString("text")
        Dim strRotate As String = context.Request.QueryString("rotate")
        Dim strBGcolor As String = context.Request.QueryString("bgcolor")

        Dim bRotate As Boolean = True

        If String.IsNullOrEmpty(strText) Then
            strText = "No Text"
        End If


        Try
            If Not String.IsNullOrEmpty(strRotate) Then
                bRotate = System.Convert.ToBoolean(strRotate)
            End If
        Catch ex As Exception

        End Try


        'Dim img As System.Drawing.Image = GenerateImage(strText, "Arial", bRotate)
        'Dim img As System.Drawing.Image = CreateBitmapImage(strText, bRotate)

        ' Generic error in GDI+
        'img.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png)

        'Dim bm As System.Drawing.Bitmap = New System.Drawing.Bitmap(img)
        'bm.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png)

        Using msTempOutputStream As New System.IO.MemoryStream
            'Dim img As System.Drawing.Image = GenerateImage(strText, "Arial", bRotate)
            Using img As System.Drawing.Image = CreateBitmapImage(strText, bRotate, strBGcolor)
                img.Save(msTempOutputStream, System.Drawing.Imaging.ImageFormat.Png)
                msTempOutputStream.Flush()

                context.Response.Buffer = True
                context.Response.ContentType = "image/png"
                context.Response.BinaryWrite(msTempOutputStream.ToArray())
            End Using ' img

        End Using ' msTempOutputStream

    End Sub ' ProcessRequest


    Private Function CreateBitmapImage(strImageText As String) As System.Drawing.Image
        Return CreateBitmapImage(strImageText, True)
    End Function ' CreateBitmapImage


    Private Function CreateBitmapImage(strImageText As String, bRotate As Boolean) As System.Drawing.Image
        Return CreateBitmapImage(strImageText, bRotate, Nothing)
    End Function


    Private Function InvertMeAColour(ColourToInvert As System.Drawing.Color) As System.Drawing.Color
        Const RGBMAX As Integer = 255
        Return System.Drawing.Color.FromArgb(RGBMAX - ColourToInvert.R, RGBMAX - ColourToInvert.G, RGBMAX - ColourToInvert.B)
    End Function



    Private Function CreateBitmapImage(strImageText As String, bRotate As Boolean, strBackgroundColor As String) As System.Drawing.Image
        Dim bmpEndImage As System.Drawing.Bitmap = Nothing

        If String.IsNullOrEmpty(strBackgroundColor) Then
            strBackgroundColor = "#E0E0E0"
        End If

        Dim intWidth As Integer = 0
        Dim intHeight As Integer = 0


        Dim bgColor As System.Drawing.Color = System.Drawing.Color.LemonChiffon ' LightGray
        bgColor = System.Drawing.ColorTranslator.FromHtml(strBackgroundColor)

        Dim TextColor As System.Drawing.Color = System.Drawing.Color.Black
        TextColor = InvertMeAColour(bgColor)

        'TextColor = Color.FromArgb(102, 102, 102)



        ' Create the Font object for the image text drawing.
        Using fntThisFont As New System.Drawing.Font("Arial", 11, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Pixel)

            ' Create a graphics object to measure the text's width and height.
            Using bmpInitialImage As New System.Drawing.Bitmap(1, 1)

                Using gStringMeasureGraphics As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmpInitialImage)
                    ' This is where the bitmap size is determined.
                    intWidth = CInt(gStringMeasureGraphics.MeasureString(strImageText, fntThisFont).Width)
                    intHeight = CInt(gStringMeasureGraphics.MeasureString(strImageText, fntThisFont).Height)

                    ' Create the bmpImage again with the correct size for the text and font.
                    bmpEndImage = New System.Drawing.Bitmap(bmpInitialImage, New System.Drawing.Size(intWidth, intHeight))

                    ' Add the colors to the new bitmap.
                    Using gNewGraphics As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmpEndImage)
                        ' Set Background color
                        'gNewGraphics.Clear(Color.White)
                        gNewGraphics.Clear(bgColor)
                        gNewGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
                        gNewGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias


                        ''''

                        'gNewGraphics.TranslateTransform(bmpEndImage.Width, bmpEndImage.Height)
                        'gNewGraphics.RotateTransform(180)
                        'gNewGraphics.RotateTransform(0)
                        'gNewGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault


                        gNewGraphics.DrawString(strImageText, fntThisFont, New System.Drawing.SolidBrush(TextColor), 0, 0)

                        gNewGraphics.Flush()

                        If bRotate Then
                            'bmpEndImage = rotateImage(bmpEndImage, 90)
                            'bmpEndImage = RotateImage(bmpEndImage, New PointF(0, 0), 90)
                            'bmpEndImage.RotateFlip(RotateFlipType.Rotate90FlipNone)
                            bmpEndImage.RotateFlip(System.Drawing.RotateFlipType.Rotate270FlipNone)
                        End If ' bRotate

                    End Using ' gNewGraphics

                End Using ' gStringMeasureGraphics

            End Using ' bmpInitialImage

        End Using ' fntThisFont

        Return bmpEndImage
    End Function ' CreateBitmapImage


    ' http://msdn.microsoft.com/en-us/library/3zxbwxch.aspx
    ' http://msdn.microsoft.com/en-us/library/7e1w5dhw.aspx
    ' http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=286
    ' http://road-blogs.blogspot.com/2011/01/rotate-text-in-ssrs.html
    Public Shared Function GenerateImage_CrappyOldReportingServiceVariant(ByVal strText As String, ByVal strFont As String, bRotate As Boolean) As System.Drawing.Image
        Dim bgColor As System.Drawing.Color = System.Drawing.Color.LemonChiffon ' LightGray
        bgColor = System.Drawing.ColorTranslator.FromHtml("#E0E0E0")


        Dim TextColor As System.Drawing.Color = System.Drawing.Color.Black
        'TextColor = System.Drawing.Color.FromArgb(255, 0, 0, 255)

        If String.IsNullOrEmpty(strFont) Then
            strFont = "Arial"
        Else
            If strFont.Trim().Equals(String.Empty) Then
                strFont = "Arial"
            End If
        End If


        'Dim fsFontStyle As System.Drawing.FontStyle = System.Drawing.FontStyle.Regular
        Dim fsFontStyle As System.Drawing.FontStyle = System.Drawing.FontStyle.Bold
        Dim fontFamily As New System.Drawing.FontFamily(strFont)
        Dim iFontSize As Integer = 8 '//Change this as needed


        ' vice-versa, because 270° turn
        'Dim height As Double = 2.25
        Dim height As Double = 4
        Dim width As Double = 1

        ' width = 10
        ' height = 10

        Dim bmpImage As New System.Drawing.Bitmap(1, 1)
        Dim iHeight As Integer = CInt(height * 0.393700787 * bmpImage.VerticalResolution) 'y DPI
        Dim iWidth As Integer = CInt(width * 0.393700787 * bmpImage.HorizontalResolution) 'x DPI

        bmpImage = New System.Drawing.Bitmap(bmpImage, New System.Drawing.Size(iWidth, iHeight))



        '// Create the Font object for the image text drawing.
        'Dim MyFont As New System.Drawing.Font("Arial", iFontSize, fsFontStyle, System.Drawing.GraphicsUnit.Point)
        '// Create a graphics object to measure the text's width and height.
        Dim MyGraphics As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmpImage)
        MyGraphics.Clear(bgColor)


        Dim stringFormat As New System.Drawing.StringFormat()
        stringFormat.FormatFlags = System.Drawing.StringFormatFlags.DirectionVertical
        'stringFormat.FormatFlags = System.Drawing.StringFormatFlags.DirectionVertical Or System.Drawing.StringFormatFlags.DirectionRightToLeft
        Dim solidBrush As New System.Drawing.SolidBrush(TextColor)
        Dim pointF As New System.Drawing.PointF(CSng(iWidth / 2 - iFontSize / 2 - 2), 5)
        Dim font As New System.Drawing.Font(fontFamily, iFontSize, fsFontStyle, System.Drawing.GraphicsUnit.Point)


        MyGraphics.TranslateTransform(bmpImage.Width, bmpImage.Height)
        MyGraphics.RotateTransform(180)
        MyGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault
        MyGraphics.DrawString(strText, font, solidBrush, pointF, stringFormat)
        MyGraphics.ResetTransform()

        MyGraphics.Flush()

        'If Not bRotate Then
        'bmpImage.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone)
        'End If

        Return bmpImage
    End Function ' GenerateImage



    ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property ' IsReusable


End Class

请注意,如果您认为这一部分缺失或需要解释,请查看相关的API文档以获得更多信息。
        Using msTempOutputStream As New System.IO.MemoryStream
            'Dim img As System.Drawing.Image = GenerateImage(strText, "Arial", bRotate)
            Using img As System.Drawing.Image = CreateBitmapImage(strText, bRotate, strBGcolor)
                img.Save(msTempOutputStream, System.Drawing.Imaging.ImageFormat.Png)
                msTempOutputStream.Flush()

                context.Response.Buffer = True
                context.Response.ContentType = "image/png"
                context.Response.BinaryWrite(msTempOutputStream.ToArray())
            End Using ' img

        End Using ' msTempOutputStream

可以替换为

img.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png)

如果你认为代码在开发服务器上运行没有问题,那么你就错了,如果你将同样的代码部署到Windows 2003 IIS 6服务器上,它很可能会抛出一个通用的GDI+异常...
然后像这样使用它:
<img alt="bla" src="GenerateImage.ashx?no_cache=123&text=Hello%20World&rotate=true" />

然而,这取决于VB.NET,它也不是普遍可移植的。(但至少将问题从客户端转移到了服务器端。) - Florian Jenn
@Florian Jenn:是的,VB.NET代码依赖于VB.NET,但你也可以使用PHP、Python、Ruby或其他语言实现相同的功能。另外,将其转换为C#,就可以在Linux、Mac或Solaris上运行mono了。 - Stefan Steiger

3

IE滤镜加上CSS转换(SafariFirefox)。

IE的支持是最早的,Safari在3.1.2中有[至少一些]支持,而Firefox直到3.1才会有支持。

或者,我建议使用Canvas/VML或SVG/VML的混合方式。(Canvas具有更广泛的支持。)


我同意眼皮无力的看法。现在这一切都是“hack”。还不够成熟,没准备好进入主流。 - Diodeus - James MacFarlane

2

以下是一种适用于纯文本和某些服务器端处理的方法:

public string RotateHtmltext(string innerHtml)
{
   const string TRANSFORMTEXT = "transform: rotate(90deg);";
   const string EXTRASTYLECSS = "<style type='text/css'>.r90 {"
                                 + "-webkit-" + TRANSFORMTEXT
                                 + "-moz-" + TRANSFORMTEXT
                                 + "-o-" + TRANSFORMTEXT
                                 + "-ms-" + TRANSFORMTEXT
                                 + "" + TRANSFORMTEXT
                                 + "width:1em;line-height:1ex}</style>";
   const string WRAPPERDIV = "<div style='display: table-cell; vertical-align: middle;'>";

   var newinnerHtml = string.Join("</div>"+WRAPPERDIV, Regex.Split(innerHtml, @"<br */?>").Reverse());

   newinnerHtml = Regex.Replace(newinnerHtml, @"((?:<[^>]*>)|(?:[^<]+))",
                                 match => match.Groups[1].Value.StartsWith("<")
                                             ? match.Groups[1].Value
                                             : string.Join("", match.Groups[1].Value.ToCharArray().Select(x=>"<div class='r90'>"+x+"</div>")),
                                 RegexOptions.Singleline);
   return EXTRASTYLECSS + WRAPPERDIV + newinnerHtml + "</div>";
}

这将会得到类似下面的结果:

<style type="text/css">.r90 {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
width: 1em;
line-height: 1ex; 
}</style>
<div style="display: table-cell; vertical-align: middle;">
<div class="r90">p</div>
<div class="r90">o</div>
<div class="r90">s</div>
</div><div style="display: table-cell; vertical-align: middle;">
<div class="r90">(</div>
<div class="r90">A</div>
<div class="r90">b</div>
<div class="r90">s</div>
<div class="r90">)</div>
</div>

http://jsfiddle.net/TzzHy/


1
另一个解决方案:
(function () {

    var make_rotated_text = function (text)
    {
        var can = document.createElement ('canvas');
        can.width = 10;
        can.height = 10;
        var ctx=can.getContext ("2d");
        ctx.font="20px Verdana";
        var m = ctx.measureText(text);
        can.width = 20;
        can.height = m.width;
        ctx.font="20px Verdana";
        ctx.fillStyle = "#000000";
        ctx.rotate(90 * (Math.PI / 180));
        ctx.fillText (text, 0, -2);
        return can;
    };

    var canvas = make_rotated_text ("Hellooooo :D");
    var body = document.getElementsByTagName ('body')[0];
    body.appendChild (canvas);

}) ();

我完全承认这很粗糙,但如果你想避免CSS膨胀,这是一个简单的解决方案。

1

我正在使用 Font Awesome 库,并且可以通过将以下内容添加到任何 HTML 元素来实现这个效果。

<div class="fa fa-rotate-270">
  My Test Text
</div>

您的里程数可能会有所不同。

1

看看这个,我在寻找解决IE 7问题的方法时发现了它。

对于纯CSS而言,这是一个非常酷的解决方案。

感谢aiboy提供的解决方案。

这里是链接

这里是我发现这个解决方案的stackoverflow链接连接到我

         .vertical-text-vibes{

                /* this is for shity "non IE" browsers
                   that dosn't support writing-mode */
                -webkit-transform: translate(1.1em,0) rotate(90deg);
                   -moz-transform: translate(1.1em,0) rotate(90deg);
                     -o-transform: translate(1.1em,0) rotate(90deg);
                        transform: translate(1.1em,0) rotate(90deg);
                -webkit-transform-origin: 0 0;
                   -moz-transform-origin: 0 0;
                     -o-transform-origin: 0 0;
                        transform-origin: 0 0;  
             /* IE9+ */    ms-transform: none;    
                   -ms-transform-origin: none;    
        /* IE8+ */    -ms-writing-mode: tb-rl;    
   /* IE7 and below */    *writing-mode: tb-rl;

            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接