WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

文字列の長さ制限、三点リーダー表示

by WebSurfer 2023年6月23日 13:52

先の記事「GridView に overflow 適用、三点リーダー表示」で、CSS の overflow: hidden と text-overflow: ellipsis を使って文字列の長さ制限するとともに三点リーダーを表示する例を紹介しましたが、文字列の中にエスケープされた文字、プロポーショナルフォント、サロゲートペア、絵文字などが含まれる場合どうなるかという話を書きます。

文字列の長さ制限、三点リーダー表示

上の画像の下側の表の description 列の各行が、文字列の長さを 320px に制限するとともに末尾を三点リーダーで表示したものです。具体的にどのようにしたかと言うと、上側の表の description 列と同じ文字列を div 要素に入れて、その div 要素に以下の CSS を適用しました。ブラウザは Chrome、フォントはメイリオ、サイズは 16px です。

<style type="text/css">
    div.style1
    {
        width: 320px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
</style>

1 行目にある < > & という文字は、実際は &lt; &gt; &amp; というエスケープされた文字列が、ブラウザ上では < > & と表示されたものです。

4 行目の絵文字 🍎 と 🍏 は UTF-16 のサロゲートペア (🍎 は 0xD83C 0xDF4E, 🍏 は 0xD83C 0xDF4F) です。👨‍🌾 は、👨 と 🌾 (おのおのサロゲートペアで 0xD83D 0xDC68 と 0xD83C 0xDF3E) を ZeroWidthJoiner (0x200D) で連結したもの、つまり、0xD83D 0xDC68 0x200D 0xD83C 0xDF3E となっています。

上の結果から分かるように、各文字の長さやバイト数とは関係なく、ブラウザ上に表示された文字列の長さで制限がかかり、CSS の width: 320px で指定された幅いっぱいに三点リーダを含めて表示されています。

上の画像ではフォントはメイリオ、サイズは 16px ですが、MS Gothic などの等幅フォントを使った場合も、フォントサイズを変えた場合も、ブラウザ上に表示される文字列の長さで制限がかかるのは同じです。

三点リーダーを表示する text-overflow:ellipsis はもともと IE の独自拡張だそうですが、最近は他のブラウザでも取り入れられているようです。Windows 10 で Chrome 114.0.5735.134, Edge 114.0.1823.58, Firefox 114.0.2, Opera 100.0.4815.21 で試してみましたが、同じ結果が得られました。

参考に、上の画像を表示するのに使った ASP.NET Web Forms アプリのコードを載せておきます。

.aspx.cs

using System;
using System.Data;

namespace WebForms1
{
    public partial class WebForm26 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // データソースとして DataTable を作成。
                DataTable dt = new DataTable();
                DataRow dr;

                dt.Columns.Add(new DataColumn("id", typeof(Int32)));
                dt.Columns.Add(
                    new DataColumn("description", typeof(string)));

                dr = dt.NewRow();
                dr["id"] = 1;
                dr["description"] = "エスケープされた < > & " +
                    "などの文字はどのようになるか?";
                dt.Rows.Add(dr);

                dr = dt.NewRow();
                dr["id"] = 2;
                dr["description"] = "Proportional Font WWWWWWWWWWW " +
                    "iiiiiiii llllll などは?";
                dt.Rows.Add(dr);

                dr = dt.NewRow();
                dr["id"] = 3;
                dr["description"] = "サロゲートペア 𠀋 𡈽 𠮟 などは" +
                    "どのようになるか?";
                dt.Rows.Add(dr);

                dr = dt.NewRow();
                dr["id"] = 4;
                dr["description"] = "絵文字 🍎 🍏 (サロゲートペア) " +
                    "👨‍🌾 (ZWJ で結合) などは?";
                dt.Rows.Add(dr);

                // 上で作成した DataTable を GridView にバインド。
                GridView1.DataSource = dt;
                GridView1.DataBind();

                GridView2.DataSource = dt;
                GridView2.DataBind();
            }
        }
    }
}

.aspx

<%@ Page Language="C#" AutoEventWireup="true"
    CodeBehind="WebForm26.aspx.cs" Inherits="WebForms1.WebForm26" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <style type="text/css">
        body {
            font-family: "メイリオ";
            font-size: 16px;
        }

        div.style1 {
            width: 320px;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <p>制限しない場合 (フォント: メイリオ, 16px)</p>
        <asp:GridView ID="GridView1"
            runat="server"
            AutoGenerateColumns="False">
            <Columns>
                <asp:BoundField DataField="id" HeaderText="id" />
                <asp:TemplateField HeaderText="description">
                    <ItemTemplate>
                        <asp:Literal ID="Literal1"
                            runat="server"
                            Text='<%# Eval("description") %>'>
                        </asp:Literal>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>

        <p>overflow:hidden で制限 (フォント: メイリオ, 16px)</p>
        <asp:GridView ID="GridView2"
            runat="server"
            AutoGenerateColumns="False">
            <Columns>
                <asp:BoundField DataField="id" HeaderText="id" />
                <asp:TemplateField HeaderText="description">
                    <ItemTemplate>
                        <div class="style1">
                            <asp:Literal ID="Literal1"
                                runat="server"
                                Text='<%# Eval("description") %>'>
                            </asp:Literal>
                        </div>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </form>
</body>
</html>

Tags: , , , ,

ASP.NET

ブラウザ画面でセンタリング

by WebSurfer 2018年11月1日 12:10

CSS のみを使ってブラウザ画面上でコンテンツを上下左右センタリングする方法を、あまり需要はないとは思いますが、せっかく考えたので備忘録として書いておきます。

センタリング表示

上の画像は、width / height を 500px / 300px に設定した div 要素を、CSS の position プロパティを使って、ブラウザ画面の中央に来るようにしたものです。ブラウザの画面のサイズを変えても自動的に中央に来るようになっています。

CSS の設定は下にアップしたコードにありますので見てください。position を absolute とし、top / left を 50%(即ち画面の中央)に指定、margin に div 要素のサイズの半分をマイナス値で設定することにより div 要素が画面の中央に来るようにオフセットしています。

position プロパティの詳しい説明&デモは MDN web docs の記事「position」にありますので見てください。要点を抜粋すると以下の通りです。

An absolutely positioned element is an element whose computed position value is absolute or fixed. The top, right, bottom, and left properties specify offsets from the edges of the element's containing block. If the element has margins, they are added to the offset.

上の画像を表示したコードを以下にアップしておきます。ASP.NET Web Forms アプリの .aspx ページを使っていますが、ASP.NET は今回の記事には直接の関係はありません。(.html ページを使うとブラウザのキャッシュをいちいち消さなければならないのが面倒なので .aspx ページを使いました)

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="0049-Centering.aspx.cs" 
    Inherits="_0049_Centering" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Centering</title>
    <style type="text/css">
        body {
            background-color: #555;
        }

        .content {
            background-color: white;
            width:500px;
            height:300px;
            position:absolute;
            top:50%;
            left:50%;
            margin-left:-250px;
            margin-top:-150px;
            overflow:scroll;
        }
    </style>
</head>
<body>
  <form id="form1" runat="server">
    <div class="content">
      <h1>
        This page is horizontally / vertically centered on 
        screen that is wider than 500 / 300 pixels.
      </h1>
      <h2>
        Resize the browser window to see the effect.
      </h2>
      <p>
        An absolutely positioned element is an element 
        whose computed position value is absolute or fixed. 
        The top, right, bottom, and left properties specify 
        offsets from the edges of the element's containing 
        block. (The containing block is the ancestor 
        relative to which the element is positioned.) 
        If the element has margins, they are added to the 
        offset.
      </p>
    </div>
  </form>
</body>
</html>

Tags:

ASP.NET

table のヘッダ、列を固定

by WebSurfer 2011年1月23日 15:17
2017/8/16 注記追加
Windows 10 IE11 では Quirks モード(IE5 相当)にしても expression 関数が働かないようで、テーブルのヘッダ・列は固定されませんのでご注意ください。この記事はもう意味がないかもしれませんが、せっかく書いたので残しておきます。

MSDN フォーラムなどで、IE の互換モード(正確には Quirks モードという IE5 以前のレンダリングエンジン)で動く table のヘッダ(tr 要素)を固定する "Freezing" という名前の css に関する質問を時々見かけます。

これは IE 独自拡張の expression 関数を使ったものですが、ListView でヘッダーを 2 行にした場合にも適用できるかどうか試してみました。結果は下の画像のように期待通り表示されました。

table のヘッダ(tr 要素)を固定

ただし、ヘッダーだけでなく列も固定すると、何故か固定した部分の border の幅が広くなってしまい、それを解決する方法が見つかっていないのが悔しいところですが。(汗)

上の画像を作ったコードは以下の通りです。Microsoft が提供している Northwind サンプルデータベースの Products テーブルを使用しています。

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title></title>
  <%--Quirks モードに設定--%>
  <meta http-equiv="X-UA-Compatible" content="IE=5" />
  <style type="text/css">
    .FreezingHeader
    {
      z-index: 10;
      position: relative;
      top: expression(this.offsetParent.scrollTop);
      background-color: #0000cc; /* ヘッダ部分の border の色 */
    }

    .FreezingCol
    {
      z-index: 1;
      left: expression(document.getElementById("freezingDiv").scrollLeft);
      position: relative;
      background-color: white;
    }

    #freezingDiv
    {
      overflow: auto;
      width: 400px;
      height: 300px;
    }

    table.style1
    {
      border-style: none; /* 指定するとスクロールでずれる */
      text-align: center;
      border-collapse: collapse;            
    }
       
    table.style1 th
    {
      border-style: solid;
      border-width: 2px;
      border-color: #0000cc;
      background-color: #6699FF;
      color: #FFFFFF;
      padding: 5px;            
    }
       
    table.style1 td
    {
      border-style: solid;
      border-width: 2px;
      border-color: #0000cc;
      padding: 5px;
    }

  </style>
</head>
<body>
  <form id="form1" runat="server">
  <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString="<%$ ConnectionStrings:Northwind %>" 
    SelectCommand=
        "SELECT [ProductID], [ProductName], [QuantityPerUnit], [UnitPrice], [UnitsInStock] 
        FROM [Products]">
  </asp:SqlDataSource>
  <div id="freezingDiv">
    <asp:ListView ID="ListView1" 
      runat="server" 
      DataKeyNames="ProductID" 
      DataSourceID="SqlDataSource1" 
      EnableModelValidation="True">
      <ItemTemplate>
        <tr>
          <td class="FreezingCol">
            <asp:Label ID="ProductIDLabel" 
              runat="server" 
              Text='<%# Eval("ProductID") %>' />
          </td>
          <td class="FreezingCol">
            <asp:Label ID="ProductNameLabel" 
              runat="server" 
              Text='<%# Eval("ProductName") %>' />
          </td>
          <td>
            <asp:Label ID="QuantityPerUnitLabel" 
              runat="server" 
              Text='<%# Eval("QuantityPerUnit") %>' />
          </td>
          <td>
            <asp:Label ID="UnitPriceLabel" 
              runat="server" 
              Text='<%# Eval("UnitPrice") %>' />
          </td>
          <td>
            <asp:Label ID="UnitsInStockLabel" 
              runat="server" 
              Text='<%# Eval("UnitsInStock") %>' />
          </td>
        </tr>
      </ItemTemplate>
      <LayoutTemplate>
        <table ID="itemPlaceholderContainer" 
          runat="server" 
          class="style1">
          <tr runat="server" class="FreezingHeader">
            <th runat="server" colspan="2" class="FreezingCol">
              ID and Name</th>
            <th runat="server" colspan="3">
              Details of Products</th>
          </tr>
          <tr runat="server" class="FreezingHeader">
            <th runat="server" class="FreezingCol">
              ProductID</th>
            <th runat="server" class="FreezingCol">
              ProductName</th>
            <th runat="server">
              QuantityPerUnit</th>
            <th runat="server">
              UnitPrice</th>
            <th runat="server">
              UnitsInStock</th>
          </tr>
          <tr ID="itemPlaceholder" runat="server">
            </tr>
        </table> 
      </LayoutTemplate>
    </asp:ListView>
  </div>
  </form>
</body>
</html>

個人的には IE 専用のハック的な方法と思っていますので、これを実際に使うことはなさそうですが、こういったこともできるということでご参考まで。

------------ 2011/4/29 追記 ------------

上の画像のように固定した部分の border の幅が広くなってしまう問題は、以下のように、class="FreezingCol" を付与した th, td 要素に inline スタイルで border の幅を指定してやることで解決できます。

・・・前略・・・
<ItemTemplate>
  <tr>
    <td class="FreezingCol" style="border-width: 1 1 1 2;">
      <asp:Label ID="ProductIDLabel" 
        runat="server" 
        Text='<%# Eval("ProductID") %>' />
    </td>
    <td class="FreezingCol" style="border-width: 1 1 1 1;">
      <asp:Label ID="ProductNameLabel" 
        runat="server" 
        Text='<%# Eval("ProductName") %>' />
    </td>
    ・・・中略・・・
</ItemTemplate>
<LayoutTemplate>
  <table ID="itemPlaceholderContainer" 
    runat="server" 
    class="style1">
    <tr runat="server" class="FreezingHeader">
      <th runat="server" colspan="2" class="FreezingCol" style="border-width: 2 1 1 2;">
        ID and Name</th>
      <th runat="server" colspan="3">
         Details of Products</th>
    </tr>
    <tr runat="server" class="FreezingHeader">
      <th runat="server" class="FreezingCol" style="border-width: 1 1 1 2;">
        ProductID</th>
      <th runat="server" class="FreezingCol" style="border-width: 1 1 1 1;">
        ProductName</th>
・・・後略・・・

Tags: , ,

ASP.NET

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar